home *** CD-ROM | disk | FTP | other *** search
Text File | 1994-01-16 | 658.7 KB | 19,821 lines |
- //JOBNAME JOB ACCOUNT,'NAME'
- //*------------------------------------------------------------------*/
- //* */
- //* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1993 */
- //* */
- //* This software is provided on an "AS IS" basis. All warranties, */
- //* including the implied warranties of merchantability and fitness, */
- //* are expressly denied. */
- //* */
- //* Provided this copyright notice is included, this software may */
- //* be freely distributed and not offered for sale. */
- //* */
- //* Changes or modifications may be made and used only by the maker */
- //* of same, and not further distributed. Such modifications should */
- //* be mailed to the author for consideration for addition to the */
- //* software and incorporation in subsequent releases. */
- //* */
- //*------------------------------------------------------------------*/
- //*
- //* GOPHER - MVS Gopher Client and Server
- //*
- //* Version: 3 Release: 1
- //*
- //* Author: Steve Bacher <seb@draper.com>
- //*
- //* Date: 16 Jan 1994
- //*
- //*-------------------------------------------------------------------
- //*
- //* This job creates the distribution libraries (PDS's).
- //*
- //* Run this JCL to create the PDS's, after customizing to suit.
- //* (Obviously, put in a good JOB statement first.)
- //* To customize the JCL, change the defaults on the //MDLOAD PROC
- //* statement to your liking, particularly the PREFIX default.
- //* You might also want to change the final qualifiers of the PDS's
- //* created - to do this, find the // EXEC MDLOAD statements and
- //* change the value of the TO parameter.
- //*
- //* See the $$README file (of the CNTL PDS, first in this stream)
- //* for the rest of the installation instructions.
- //*
- //MDLOAD PROC CLS='*',BS='6160',U='3380',V='',
- // TRK1='60',TRK2='10',DIR='35',RLSE='RLSE',
- // PREFIX='GOPHER.INSTALL.'
- //*
- //IEBUPDTE EXEC PGM=IEBUPDTE,PARM=NEW
- //SYSPRINT DD SYSOUT=&CLS
- //SYSUT2 DD DISP=(NEW,CATLG,DELETE),DSN=&PREFIX.&TO,
- // DCB=(RECFM=FB,LRECL=80,BLKSIZE=&BS),
- // SPACE=(TRK,(&TRK1,&TRK2,&DIR),&RLSE),UNIT=&U,VOL=SER=&V
- //*
- // PEND
- //*
- //CNTL EXEC MDLOAD,BS='6160',TRK1='10',TRK2='1',TO='CNTL'
- //SYSIN DD DATA,DLM='?!'
- ./ ADD NAME=$$README
-
- ------------------------------------------------------------------------
-
- Copyright (c) The Charles Stark Draper Laboratory, Inc.,1992,1993,1994
-
- MVS Gopher Server originally by Shawn Hart (Univ. of Delaware).
-
- This software is provided on an "AS IS" basis. All warranties,
- including the implied warranties of merchantability and fitness,
- are expressly denied.
-
- Provided this copyright notice is included, this software may
- be freely distributed and not offered for sale.
-
- Changes or modifications may be made and used only by the maker
- of same, and not further distributed. Such modifications should
- be mailed to the author for consideration for addition to the
- software and incorporation in subsequent releases.
-
- ------------------------------------------------------------------------
-
- MVS Gopher Client
-
- Original Author: Steve Bacher <seb@draper.com>
-
- MVS Gopher Server
-
- Original Author: Shawn Hart <shart@indial1.io.com>
-
- Various enhancements and customizations to both the client and the
- server have been contributed by:
-
- Steve Bacher <seb@draper.com>
- Lou Joseph <cwmy5c@irishmvs.cc.nd.edu>
- Denis DeLaRoca <csp1dwd@mvs.oac.ucla.edu>
- Dwight Cook <sysdc@uokmvsa.backbone.uoknor.edu>
- Rachna Agrawal <rachna@clemson.clemson.edu>
-
- ------------------------------------------------------------------------
-
- Contents of PDS's belonging to Gopher distribution:
-
- Member PDS Type Description
-
- $$README CNTL This file
- $CHANGES CNTL Changes since the last release
- ACCESS CNTL Sample server access file
- ALLOAD CNTL JCL to allocate additional Gopher libraries
- COMPILE CNTL JCL to compile *** SOURCE DISTRIBUTION ONLY ***
- GOPHERD CNTL JCL to run the GOPHER server in batch (No TSO)
- GOPHERT CNTL JCL to run the GOPHER server in batch (w. TSO)
- HELP CNTL TSO Help for Gopher client
- INSTALLC CNTL How to install the GOPHER MVS client
- INSTALLS CNTL How to install the GOPHER MVS server
- LINKC CNTL JCL to linkedit the client load module
- LINKS CNTL JCL to linkedit the server load modules
- LINKX CNTL JCL to linkedit the auxiliary load modules
- MENU CNTL Initial Gopher server menu
- PARMS CNTL Sample Gopher startup parameters
- SECURE CNTL Discussion about making secure REXX scripts
- GOPHER CLIST Exec by which users invoke the Gopher client
- NNMFIUCV CLIST Exec to check for multiple socket applications
- REXXTEST CLIST REXX exec to test the REXX interface with
- TSOHELP CLIST Sample REXX exec for Gopher TSO HELP menu hole
- G... CLIST REXX exec helpers
- GGM... PANEL ISPF regular panels
- ABOUT... ABOUT "About This Gopher" text
- GG... H C headers *** SOURCE DISTRIBUTION ONLY ***
- GG... C C source *** SOURCE DISTRIBUTION ONLY ***
- GG... OBJ Object modules *** OBJECT DISTRIBUTION ONLY ***
-
- --------------------------------------------------------------------
-
- Where to Go from Here:
-
- To install the GOPHER MVS client, read member INSTALLC.
-
- To install the GOPHER MVS server, read member INSTALLS.
-
- Note:
-
- You may install only the client, only the server, or both the
- client and the server. It is purely up to what your needs are.
-
- --------------------------------------------------------------------
-
- Questions? Comments? Suggestions? Gripes? Please email to...
-
- Steve Bacher <seb@draper.com>
-
- ./ ADD NAME=$CHANGES
- Changes:
-
- November 93 - Version 3 Release 1
-
- Server Enhancements
-
- Support for binary files, including image files, in the
- remote FTP gateway. Most file types are supported for
- the server, and the client will support some binary types,
- although they cannot be viewed or printed well.
-
- The REXX interface has been completely redesigned. It is
- not compatible with the previous version, but migration
- should be easy. Among other things, you can now run REXX
- execs from a non-TSO-environment server, which will allow
- multithreading of client requests that trigger REXX execs.
-
- The access file now supports wildcarding in the file name
- specifications. Because of this, you must stop and
- restart the gopher server when you change the access file.
- The rules are processed differently.
-
- Additional logging (via write-to-programmer) in a mode
- compatible with the format produced by the U of Minn
- gopher daemon.
-
- Rudimentary support for gopher+ has been added on an
- experimental basis. Do not rely on this, because it is
- not complete by any means.
-
- Client Enhancements
-
- Printing allows destination in the form nodename.userid.
-
- INITFILE keyword added for a differently named GOPHERRC.
-
- 07 Aug 93 - Version 2 Release 2
-
- Remote FTP Gateway
- Enhanced CSO client option
- Configurable GOPHERRC: domain and telnet may be specified
- Object-code-only distribution for those without C compilers
- Improvements to TSO GOPHER exec for users without XPROC
- or without C runtime in linklist
- DD:ddname(member) works now for nested PDS member
- references, making installing the ABOUT PDS simpler
- "E" and "P" work without "S" having to be done first
-
- 20 Mar 93 - Version 2 Release 1
-
- Improved browse function
- Printing support
- Bookmark support
- New commands: PRT, INFO, MENU, BOOKMARK
- Configurable startup parameter file
- Ability to run multiple servers on same MVS
-
- 07 Dec 92 - Customizations to support SNS/TCPAccess
-
- 19 Oct 92 - Improvements in initial startup and GOPHERRC customization
-
- ./ ADD NAME=ACCESS
- !
- ! Format of entries:
- !
- ! filename (fully qualified, all uppercase, no quotes)
- ! can be "DD:DDNAME" or "EXEC:EXECNAME"
- !
- ! followed by names of hosts which are authorized to access the data.
- ! If no host name list is present, all hosts are authorized
- !
- ! You may specify the same file name more than once, if you need
- ! more lines to put host names on.
- !
- ! Individual PDS members must be specified separately. A PDS without
- ! a member name establishes access only to the PDS directory.
- !
- ! Note that the default directory MUST be in this table.
- !
- ! Also note that in the case of EXECs, the EXEC must live in the
- ! library allocated to GGEXEC in the Gopher server JCL.
- !
- ! *** ANY DATA SET REFERENCED BY ANY EXEC IN THAT LIBRARY IS FULLY
- ! *** ACCESSIBLE TO GOPHER REGARDLESS OF THIS TABLE! USE THIS TABLE
- ! *** TO GOVERN CONTROL TO THE EXEC ITSELF!!!
-
- !
- ! below is default directory spec, which MUST be in this table
- !
- DD:GGGOPHER
-
- !
- ! Use the following for "About This Gopher".
- ! Free free to specify the name of your MVS client host(s)
- ! for information pertinent to MVS only. mvs1 and mvs2 are examples.
- !
- DD:GGABOUT
- DD:GGABOUT(ABOUT)
- DD:GGABOUT(ABOUTC) mvs1 mvs2
- DD:GGABOUT(ABOUTCD) mvs1 mvs2
- DD:GGABOUT(ABOUTCF) mvs1 mvs2
- DD:GGABOUT(ABOUTCO) mvs1 mvs2
- DD:GGABOUT(ABOUTCQ) mvs1 mvs2
- DD:GGABOUT(ABOUTCS) mvs1 mvs2
- DD:GGABOUT(ABOUTCSC) mvs1 mvs2
- DD:GGABOUT(ABOUTCSL) mvs1 mvs2
- DD:GGABOUT(ABOUTCSM) mvs1 mvs2
- DD:GGABOUT(ABOUTCSR) mvs1 mvs2
- DD:GGABOUT(ABOUTCSW) mvs1 mvs2
- DD:GGABOUT(ABOUTCSX) mvs1 mvs2
- DD:GGABOUT(ABOUTCX) mvs1 mvs2
- DD:GGABOUT(ABOUTS) mvs1 mvs2
- DD:GGABOUT(ABOUTSA) mvs1 mvs2
- DD:GGABOUT(ABOUTSP) mvs1 mvs2
- DD:GGABOUT(ABOUTW)
- DD:GGABOUT(FAQ)
-
- !
- ! Here's how to do REXX execs. Note - no arguments, only exec names
- !
- EXEC:CHECKLST client1 client2 mvs
- EXEC:WAISDIR
- EXEC:WAISLIST
- EXEC:WAISSRCH
-
- ANY.PUBLIC.SEQ.DS
- ANY.SEMI.PUBLIC.SEQ.DS goodclient1 goodclient2
- ANY.SEMI.PUBLIC.SEQ.DS goodclient3 goodclient4
-
- ! PDS without member name provides access to directory only
- ! All member names must be explicitly listed to be accessible.
-
- ANY.PUBLIC.PDS
- ANY.PUBLIC.PDS(MEMBER1)
- ANY.PUBLIC.PDS(MEMBER2)
- ANY.PUBLIC.PDS(MEMBER3)
- ANY.PUBLIC.PDS(MEMBER4)
-
-
- ANY.SEMI.PUBLIC.PDS goodclient1 goodclient2
- ANY.SEMI.PUBLIC.PDS goodclient3 goodclient4
- ANY.SEMI.PUBLIC.PDS(MEMBER1) goodclient1
- ANY.SEMI.PUBLIC.PDS(MEMBER2) goodclient2
- ANY.SEMI.PUBLIC.PDS(MEMBER3) goodclient3
- ANY.SEMI.PUBLIC.PDS(MEMBER4) goodclient4
-
- ./ ADD NAME=ALLOAD
- //JOBNAME JOB ACCOUNT,'NAME'
- //* */
- //* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 */
- //* */
- //* This software is provided on an "AS IS" basis. All warranties, */
- //* including the implied warranties of merchantability and fitness, */
- //* are expressly denied. */
- //* */
- //* Provided this copyright notice is included, this software may */
- //* be freely distributed and not offered for sale. */
- //* */
- //* Changes or modifications may be made and used only by the maker */
- //* of same, and not further distributed. Such modifications should */
- //* be mailed to the author for consideration for addition to the */
- //* software and incorporation in subsequent releases. */
- //* */
- //*
- //* Allocate GOPHER load and object libraries before install
- //*
- //GGALLOC PROC U='3380',V=''
- //*
- //IEFBR14 EXEC PGM=IEFBR14
- //ALLOCDD DD DISP=(NEW,CATLG,DELETE),DSN=&LIB,
- // DCB=(RECFM=&RF,LRECL=&LR,BLKSIZE=&BS),
- // SPACE=(&BS,(&PRI,&SEC,&DIR)),UNIT=&U,VOL=SER=&V
- //*
- // PEND
- //*
- //* The ALLOCL step allocates the load library from which the
- //* executable program will be run. If you intend to place the
- //* executable into an existing library, you can skip this step.
- //* Otherwise, the name must match the name used on the LOADLIB
- //* parameter of the GGLINK procedure in the LINK* JCL steps.
- //*
- //* If you want separate libraries for the client and the server,
- //* just duplicate this step and give the LIB's different names.
- //*
- //* The ALLOCO step allocates the object library into which the
- //* source modules will be compiled. This library is required
- //* for the compile and link steps, but is not required for run
- //* time execution. However, you may wish to keep the object
- //* library around in case there are fixes for which you will be
- //* recompiling individual Gopher source modules.
- //*
- //ALLOCL EXEC GGALLOC,PRI=50,SEC=50,DIR=35,RF=U,LR=,BS=6233,
- // LIB='GOPHER.LOAD'
- //ALLOCO EXEC GGALLOC,PRI=50,SEC=50,DIR=35,RF=FB,LR=80,BS=2960,
- // LIB='GOPHER.INSTALL.OBJ'
- //*
- ./ ADD NAME=COMPILE
- //JOBNAME JOB ACCOUNT,'NAME'
- //* */
- //* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 */
- //* */
- //* This software is provided on an "AS IS" basis. All warranties, */
- //* including the implied warranties of merchantability and fitness, */
- //* are expressly denied. */
- //* */
- //* Provided this copyright notice is included, this software may */
- //* be freely distributed and not offered for sale. */
- //* */
- //* Changes or modifications may be made and used only by the maker */
- //* of same, and not further distributed. Such modifications should */
- //* be mailed to the author for consideration for addition to the */
- //* software and incorporation in subsequent releases. */
- //* */
- //*********************************************************************
- //*
- //* Compile some or all GOPHER C/370 sources to make the SYSLIN input
- //* to the linkedit of the executable Gopher load module(s).
- //*
- //GGCC PROC MEMBER=,
- // SRCLIB='GOPHER.INSTALL.C', GOPHER C source PDS
- // HDRLIB='GOPHER.INSTALL.H', GOPHER C headers PDS
- // OBJLIB='GOPHER.INSTALL.OBJ', GOPHER object library
- // COMMHDR='TCPIP.COMMMAC', C/370 TCP/IP headers
- // C370HDR='SYS1.EDCHDRS', C/370 standard headers
- // SYSMSGS='SYS1.EDCMSGS', C/370 messages file
- // SYSMSGM='EDCMSGE', C/370 message member
- // VIOUNIT=VIO, Temporary disk unit
- // OUTCLAS='*', SYSOUT class
- // CPARMS='SOURCE EXPMAC NOAGGR NOXREF', Compile parameters
- // TEST=TEST TEST or NOTEST
- //*
- //CCOMP EXEC PGM=EDCCOMP,PARM='MARGINS(1,72) &TEST &CPARMS'
- //SYSMSGS DD DISP=SHR,DSN=&SYSMSGS(&SYSMSGM)
- //SYSIN DD DISP=SHR,DSN=&SRCLIB(&MEMBER)
- //SYSLIN DD DISP=OLD,DSN=&OBJLIB(&MEMBER)
- //SYSLIB DD DISP=SHR,DSN=&COMMHDR
- // DD DISP=SHR,DSN=&C370HDR
- //USERLIB DD DISP=SHR,DSN=&HDRLIB
- //SYSPRINT DD SYSOUT=&OUTCLAS
- //SYSCPRT DD SYSOUT=&OUTCLAS
- //SYSUT1 DD DSN=&&SYSUT1,UNIT=&VIOUNIT,DISP=(NEW,DELETE),
- // SPACE=(32000,(30,30)),DCB=(RECFM=FB,LRECL=80,BLKSIZE=3200)
- //SYSUT4 DD DSN=&&SYSUT4,UNIT=&VIOUNIT,DISP=(NEW,DELETE),
- // SPACE=(32000,(30,30)),DCB=(RECFM=FB,LRECL=80,BLKSIZE=3200)
- //SYSUT6 DD DSN=&&SYSUT6,UNIT=&VIOUNIT,DISP=(NEW,DELETE),
- // SPACE=(32000,(30,30)),DCB=(RECFM=FB,LRECL=3200,BLKSIZE=12800)
- //SYSUT7 DD DSN=&&SYSUT7,UNIT=&VIOUNIT,DISP=(NEW,DELETE),
- // SPACE=(32000,(30,30)),DCB=(RECFM=FB,LRECL=3200,BLKSIZE=12800)
- //SYSUT8 DD DSN=&&SYSUT8,UNIT=&VIOUNIT,DISP=(NEW,DELETE),
- // SPACE=(32000,(30,30)),DCB=(RECFM=FB,LRECL=3200,BLKSIZE=12800)
- //SYSUT9 DD DSN=&&SYSUT9,UNIT=&VIOUNIT,DISP=(NEW,DELETE),
- // SPACE=(32000,(30,30)),DCB=(RECFM=VB,LRECL=137,BLKSIZE=882)
- //SYSUT10 DD SYSOUT=&OUTCLAS
- //*
- // PEND
- //*
- //GGACCES EXEC GGCC,MEMBER=GGACCES
- //GGALLOC EXEC GGCC,MEMBER=GGALLOC
- //GGASVC EXEC GGCC,MEMBER=GGASVC
- //GGBARF EXEC GGCC,MEMBER=GGBARF
- //GGBIN EXEC GGCC,MEMBER=GGBIN
- //GGBKMGR EXEC GGCC,MEMBER=GGBKMGR
- //GGCLIEN EXEC GGCC,MEMBER=GGCLIEN
- //GGCLRTX EXEC GGCC,MEMBER=GGCLRTX
- //GGCONN EXEC GGCC,MEMBER=GGCONN
- //GGCSO EXEC GGCC,MEMBER=GGCSO
- //GGDBM EXEC GGCC,MEMBER=GGDBM
- //GGDFAIL EXEC GGCC,MEMBER=GGDFAIL
- //GGDIR EXEC GGCC,MEMBER=GGDIR
- //GGDISC EXEC GGCC,MEMBER=GGDISC
- //GGDISPL EXEC GGCC,MEMBER=GGDISPL
- //GGDSOPT EXEC GGCC,MEMBER=GGDSOPT
- //GGDUMP EXEC GGCC,MEMBER=GGDUMP
- //GGESRVR EXEC GGCC,MEMBER=GGESRVR
- //GGFREEM EXEC GGCC,MEMBER=GGFREEM
- //GGFTP EXEC GGCC,MEMBER=GGFTP
- //GGGETDS EXEC GGCC,MEMBER=GGGETDS
- //GGGETM EXEC GGCC,MEMBER=GGGETM
- //GGGOFOR EXEC GGCC,MEMBER=GGGOFOR
- //GGGSRVL EXEC GGCC,MEMBER=GGGSRVL
- //GGIERR EXEC GGCC,MEMBER=GGIERR
- //GGIGET EXEC GGCC,MEMBER=GGIGET
- //GGINFO EXEC GGCC,MEMBER=GGINFO
- //GGISPF EXEC GGCC,MEMBER=GGISPF
- //GGIVGET EXEC GGCC,MEMBER=GGIVGET
- //GGIVPUT EXEC GGCC,MEMBER=GGIVPUT
- //GGMENU EXEC GGCC,MEMBER=GGMENU
- //GGMTFER EXEC GGCC,MEMBER=GGMTFER
- //GGOUTS EXEC GGCC,MEMBER=GGOUTS
- //GGOUTTX EXEC GGCC,MEMBER=GGOUTTX
- //GGPMSG EXEC GGCC,MEMBER=GGPMSG
- //GGPROC EXEC GGCC,MEMBER=GGPROC
- //GGREXX EXEC GGCC,MEMBER=GGREXX
- //GGSERVE EXEC GGCC,MEMBER=GGSERVE
- //GGSLEEP EXEC GGCC,MEMBER=GGSLEEP
- //GGSOCKT EXEC GGCC,MEMBER=GGSOCKT
- //GGSOPT EXEC GGCC,MEMBER=GGSOPT
- //GGSTASK EXEC GGCC,MEMBER=GGSTASK
- //GGTEMP EXEC GGCC,MEMBER=GGTEMP
- //GGTNET EXEC GGCC,MEMBER=GGTNET
- //GGTSO EXEC GGCC,MEMBER=GGTSO
- //GGTYPE EXEC GGCC,MEMBER=GGTYPE
- //GGUNALC EXEC GGCC,MEMBER=GGUNALC
- //GGVIEW EXEC GGCC,MEMBER=GGVIEW
- //GGVTX EXEC GGCC,MEMBER=GGVTX
- //GGWAIS EXEC GGCC,MEMBER=GGWAIS
- //GGWHOIS EXEC GGCC,MEMBER=GGWHOIS
- //GGWTO EXEC GGCC,MEMBER=GGWTO
- //GGXTX EXEC GGCC,MEMBER=GGXTX
- //XGALLOC EXEC GGCC,MEMBER=XGALLOC
- //XGSLEEP EXEC GGCC,MEMBER=XGSLEEP
- //XGWTO EXEC GGCC,MEMBER=XGWTO
- //*
- ./ ADD NAME=GOPHERD
- //GOPHERD PROC MODULE=GGSERVER,
- // STEPLIB='GOPHER.LOAD',
- // EXECLIB='GOPHER.EXEC',
- // ACCESS='GOPHER.ACCESS',
- // ABOUT='GOPHER.ABOUT',
- // MENU='GOPHER.MENU',
- // PARMS='GOPHER.PARMS',
- // VIO=SYSVIO,
- // STDERR='*',
- // STDOUT='*',
- // GPARM=
- //*
- //*********************************************************************
- //* *
- //* GOPHER daemon, by Shawn Hart (U.Del.) and Steve Bacher (D.Lab.) *
- //* *
- //* Straight batch (no TSO access) *
- //* *
- //*********************************************************************
- //*
- //GOPHERD EXEC PGM=&MODULE,PARM='&GPARM'
- //STEPLIB DD DISP=SHR,DSN=&STEPLIB
- //GGEXEC DD DISP=SHR,DSN=&EXECLIB
- //SYSTSPRT DD UNIT=&VIO,SPACE=(TRK,(100,100)),RECFM=VBA,LRECL=255
- //SYSERR DD SYSOUT=&STDERR
- //SYSPRINT DD SYSOUT=&STDOUT
- //SYSTSIN DD DUMMY
- //SYSIN DD DUMMY
- //GGDEBUG DD SYSOUT=*
- //GGABOUT DD DISP=SHR,DSN=&ABOUT
- //GGACCESS DD DISP=SHR,DSN=&ACCESS
- //GGGOPHER DD DISP=SHR,DSN=&MENU
- //GGPARMS DD DISP=SHR,DSN=&PARMS
- ./ ADD NAME=GOPHERT
- //GOPHERD PROC MODULE=GGSERVER,
- // STEPLIB='GOPHER.LOAD',
- // EXECLIB='GOPHER.EXEC',
- // ACCESS='GOPHER.ACCESS',
- // ABOUT='GOPHER.ABOUT',
- // MENU='GOPHER.MENU',
- // PARMS='GOPHER.PARMS',
- // VIO=SYSVIO,
- // STDERR='*',
- // STDOUT='*',
- // GPARM=
- //*
- //*********************************************************************
- //* *
- //* GOPHER daemon, by Shawn Hart (U.Del.) and Steve Bacher (D.Lab.) *
- //* *
- //* Batch with TSO environment - required only to run REXX execs *
- //* that use TSO services *
- //* *
- //*********************************************************************
- //*
- //GOPHERD EXEC PGM=IKJEFT01,DYNAMNBR=128,REGION=8M,
- // PARM='&MODULE &GPARM'
- //STEPLIB DD DISP=SHR,DSN=&STEPLIB
- //GGEXEC DD DISP=SHR,DSN=&EXECLIB
- //SYSTSPRT DD UNIT=&VIO,SPACE=(TRK,(100,100)),RECFM=VBA,LRECL=255
- //SYSERR DD SYSOUT=&STDERR
- //SYSPRINT DD SYSOUT=&STDOUT
- //SYSTSIN DD DUMMY
- //SYSIN DD DUMMY
- //GGDEBUG DD SYSOUT=*
- //GGABOUT DD DISP=SHR,DSN=&ABOUT
- //GGACCESS DD DISP=SHR,DSN=&ACCESS
- //GGGOPHER DD DISP=SHR,DSN=&MENU
- //GGPARMS DD DISP=SHR,DSN=&PARMS
- ./ ADD NAME=HELP
- )F Function -
-
- GOPHER is a distributed document delivery service, or, more generally,
- a networked information retrieval service. It allows you to access
- numerous types of data on various hosts in a transparent fashion.
- GOPHER presents you with a hierarchical display of information sources
- which are accessed via a client/server communications link.
-
- There are GOPHER clients for all common hardware platforms. The MVS
- version runs as an ISPF dialog application.
-
- When you use the GOPHER client, information about your use of GOPHER
- is stored in a data set called GOPHERRC. If you don't have one,
- GOPHER will create it for you. You can specify a different name
- for this data set with the INITFILE keyword.
-
- You can save Gopher information in bookmark files. See the
- help for operand BOOKMARK for details.
-
- For more information on customizing your GOPHER environment, get
- into Gopher and select "About This GOPHER".
-
- )I GOPHLOC - local GOPHER help goes in member GOPHLOC
-
- )X Syntax -
-
- %GOPHER
- LOCAL
- BOOKMARK(datasetname)
- INITFILE(gopherrcname)
- SERVER(hostname)
- PATH(pathname)
- PORT(portnumber)
- DESCRIPTION(text)
- FORCE
- DEBUG
- TEST
-
- Required: none
-
- Defaults: INITFILE defaults to tsouserid.GOPHERRC
-
- )O Operands -
-
- ))LOCAL
-
- Specify LOCAL if you want to enter GOPHER in "serverless"
- mode - i.e. start up with your private GOPHER menu.
- Specifying LOCAL accomplishes two things:
-
- (1) It sets the server to "-", meaning local access.
- Therefore, you must also provide a path, either
- via the PATH operand or via a "localmenu:" spec
- in your GOPHERRC file.
-
- (2) It allows you to use GOPHER even if there are
- other TCP/IP socket applications active elsewhere
- in your TSO session. However, it will not allow
- you to connect to any GOPHER servers, even if you
- have a local menu item that points to one.
-
- For information on how to set up GOPHER menus, get into
- GOPHER and select "About This Gopher".
-
- ))BOOKMARK(datasetname)
-
- The name of a data set containing Gopher bookmarks,
- using normal TSO data set naming conventions.
-
- You can create bookmarks in GOPHER by using the "B"
- selection code next to a menu item, or by using the
- BOOKMARK command while browsing an entry. GOPHER will
- append an entry for the selected item to the end of
- the data set that you specify when asked.
-
- To access this bookmark in a Gopher session, you can use
- the MENU command from any Gopher menu display, or you can
- start Gopher with a specific bookmark file.
-
- ))INITFILE(gopherrcname)
-
- The name of a data set containing startup information,
- commonly referred to as your "GOPHERRC" file. If this
- file does not exist, it will be automatically created.
- The default for this name is tsouserid.GOPHERRC.
-
- ))SERVER(hostname)
-
- The host name (or IP address) of a Gopher server.
- If this is not given, GOPHER looks in your GOPHERRC
- to find what server to connect to. If it can't find
- an appropriate specification, you will have to enter
- a server name on the startup panel.
-
- A server name of a single minus sign (-) is a special
- case, signifying local (serverless) access to your
- own private GOPHER data. In this case, you must tell
- GOPHER where your menu is, either via the PATH operand
- or in the GOPHERRC file.
-
- ))PATH(pathname)
-
- The path name to be passed to the Gopher server, or
- used in local access as your initial menu. Although
- the exact interpretation of the pathname string varies
- depending on the server, both the MVS server and the
- local GOPHER access feature interpret the pathname
- as the FULLY QUALIFIED WITHOUT QUOTES name of an MVS
- data set containing a gopher menu. For information
- about the format of a gopher menu, see operand MENU.
-
- ))PORT(portnumber)
-
- You should never need to specify this field unless
- someone has set up a special kind of Gopher server that
- requires a unique port number. In such a case, you
- would generally use this along with the SERVER operand.
-
- ))DESCRIPTION(text)
-
- A text string giving the heading to be displayed for
- the initial directory of Gopher goodies. Normally
- either the Gopher server or the Gopher client will
- have a default value for this, or you can specify
- a description of your liking in your GOPHERRC file.
- You can also use this to override the description
- generated when you use the BOOKMARK operand to start up.
-
- ))FORCE
-
- GOPHER tries to determine if there is a TCP/IP socket
- application active elsewhere in your TSO environment
- before starting up, to prevent TCP/IP errors. If it
- tells you that there is another client active but in
- truth there is none and you know it, you can use the
- FORCE keyword to make GOPHER proceed whether it finds
- this to be the case or not.
-
- Using the LOCAL operand is one way to avoid this entire
- scenario. However, that won't allow you to access any
- Gopher servers on the network.
-
- ))DEBUG
-
- Set debugging mode on. You must preallocate a file to
- ddname GGDEBUG for this to work. This can be allocated
- to the terminal or a log file. When debug mode is on,
- messages describing memory allocation and deallocation
- and GOPHER queries sent are dumped to the debug file.
-
- ))TEST
-
- Activate C/370 interactive test (INSPECT). GOPHER must
- have been compiled with the TEST option for this to be
- effective. Note that you can also issue the TEST command
- inside GOPHER to get to INSPECT, again provided that
- GOPHER was compiled with the TEST option.
-
- ./ ADD NAME=INSTALLC
-
- Directions for Installing the GOPHER MVS Client
-
- where @ is the install prefix from the unload and $ is a system prefix
-
- Summary:
-
- 1. (all users) Customize @.H - GGUSER
- 2. (all users) Customize @.CNTL - ALLOAD
- 3. (all users) Customize @.CNTL - COMPILE
- 4. (all users) Customize @.CNTL - LINKC
- 5. (all users) Customize @.CLIST - GOPHER
- 6. (if not ISPF V3) Edit @.PANEL - GGMP*
- 7. (all users) Submit @.CNTL - ALLOAD ==> $.LOAD, @.OBJ
- 8. (all users) Submit @.CNTL - COMPILE --> @.OBJ(*)
- 9. (all users) Submit @.CNTL - LINKC --> $.LOAD(GG*)
- 10.(REXX users) Submit @.CNTL - LINKX --> $.LOAD(XG*)
- 11.(all users) Install @.CNTL - HELP --> $.HELP(GOPHER)
- 12.(all users) Install @.CLIST - GOPHER --> $.CLIST(GOPHER)
- 13.(all users) Install @.CLIST - NNMFIUCV --> $.CLIST(NNMFIUCV)
- 14.(REXX users) Install @.CLIST - * --> $.CLIST(*)
- 15.(all users) Install @.PANEL - * --> $.PANEL(*)
- 16.(all users) Install @.ABOUT - * --> $.ABOUT(*)
-
- System libraries to be updated:
-
- $.LOAD - specified in .CNTL(ALLOAD)
- $.OBJ - specified in .CNTL(ALLOAD)
- $.HELP - your existing logon-time TSO HELP (SYSHELP) library
- $.CLIST - your existing logon-time TSO CLIST (SYSPROC) library
- $.PANEL - your existing logon-time ISPF PANEL (ISPPLIB) library
- $.ABOUT - a new PDS you make yourself, or use the install copy
-
- Assuming you have unloaded all the install PDS's:
-
- 1. Customize the GGUSER header file as shown by the comments therein.
- Note in particular the defines for your TCP/IP and your C compiler.
- There are changes to the linkedit JCL that are related to these.
-
- 2,3,4. Customize the ALLOAD, COMPILE and LINKC JCL members to reflect
- your local conventions. Note: If you intend to place the executable
- into an existing library, you can suppress that part of the ALLOAD JCL.
- The name of the data set created must match across both members.
-
- *********************************************************************
-
- IMPORTANT: If you are running TCP/IP V2R2 or higher on MVS, you must
- change the following library names in the compile and link JCL:
-
- TCPIP.COMMMAC should be changed to TCPIP.SEZACMAC
- TCPIP.COMMTXT should be changed to TCPIP.SEZACMTX
-
- If you are using SNS/TCPAccess, use these library names, or
- whatever names are defined at your installation:
-
- TCPIP.COMMMAC should be changed to SNSTCP.V110.H
- TCPIP.COMMTXT should be changed to SNSTCP.V110.CILIB
-
- If you are using SAS/C, change CEESTART to MAIN in the linkedit
- ENTRY control statement.
-
- *********************************************************************
-
- Note: If you have defined C370V1 in the GGUSER header file, you must
- also include the system linklist load library or libraries containing
- ISPLINK, ISPEXEC and IKJEFF18 when linking. Otherwise you may delete
- the lines from the linkedit JCL that reference them.
-
- Note: You need not include the PASCAL libraries or the AMPZMVSB
- module if you are using TCP/IP Version 2 or higher, in which case
- you must also define TCPIPV2 in the GGUSER headerfile.
-
- 5. Customize the GOPHER exec to define the names of the MVS libraries
- to contain the panel and load library members. The load library must
- be the one specified in the ALLOAD JCL, if you are creating it anew.
- Observe the comments relating to the use of LIBDEF and ISPF APPLIDs.
-
- It is in the GOPHER exec that you will also customize the name of the
- default Gopher server. Note that the user's GOPHERRC file gets built
- from the contents of this exec.
-
- You may configure the GOPHER exec to use XPROC to parse the operands
- given to it by the TSO user. If you don't have XPROC, you should get
- it, because the user can take advantage of all the power of TSO CLIST
- style parsing if you do. The GOPHER exec contains some code that
- emulates full TSO parsing, but it isn't as robust or flexible as true
- XPROC parsing. You can get XPROC from ftp.mic.ucla.edu in directory
- /pub/mvs/util, as part of the TSOREXX distribution.
-
- If the C/370 runtime library is not in the link list or otherwise
- available to ISPF at execution time, you may arrange for it to be
- allocated via LIBDEF in the GOPHER exec by setting "crunlibs".
-
- 6. If you are running ISPF Version 2 or earlier, edit the GOPHER panels
- whose names begin "GGMP...". These are popups, and will not work
- under ISPF Version 2 unless you change the )BODY line. Remove the
- WINDOW(...) parameter from the )BODY line of each panel so that the
- line just says )BODY or )BODY EXPAND(``), as the case may be.
-
- 7. Submit the ALLOAD JCL to allocate the load library from which the
- executable program will be run, as well as the object library in which
- the compiled object modules will be stored.
-
- 8. Submit the COMPILE JCL to compile all the C sources and create the
- required object modules in the object library built in the above step.
- Note that this compiles all the modules for both the client and the
- server. If you are installing both, you need not repeat this step.
-
- 9. Submit the LINKC JCL to create the executable Gopher load module
- from the object modules created in the above step. This will create
- or replace the load module GGCLIENT.
-
- Note: The linkedit must complete with a return code of zero. If not,
- don't use the resultant load module. Check the libraries you specified
- on the link step to see what went wrong.
-
- In the future, if you have to recompile individual modules, you can use
- the same JCL to compile only those modules, and the link will include
- the new modules in the existing executable load module. To do this,
- you must retain the object library built above.
-
- 10. Submit the LINKX JCL to create the auxiliary Gopher load modules
- from the object modules created in the above step. This will create
- or replace load modules named XG..., used by the REXX interface.
-
- 11. Copy the help member (HELP) from the CNTL PDS into your local TSO
- HELP library under the name GOPHER. You may also create an additional
- HELP member called GOPHLOC containing information local to your site,
- if you wish.
-
- 12. Copy the GOPHER exec from the CLIST PDS into your local TSO CLIST
- library under the name GOPHER. You may install it in a REXX exec
- library allocated to SYSEXEC if that is your convention for REXX execs
- as opposed to CLISTs.
-
- 13. If you install the GOPHER exec, you must also install
- the NNMFIUCV exec in the same library. This exec implements a rude
- check for an existing TCP/IP socket application (e.g. another GOPHER)
- in a different PIE MultiTSO session. It prevents your users from
- crashing TCP/IP, so it is highly recommended that you make use of it.
-
- 14. Install the remainder of the execs in a library that will be
- accessible to the client in local mode (possibly the same library).
- These execs are required by the new REXX interface.
-
- 15. Copy all the members of the panel PDS into the ISPF panel library
- specified in the GOPHER exec.
-
- 16. Create the "About This Gopher" PDS from the ABOUT PDS. This has
- all the text users should see when they select the "About This Gopher"
- item from the MVS client. It also contains all the documentation you
- need about setting up the client and the server, as well as creating
- menus and REXX execs for use with MVS Gopher. You may have already
- done this as part of the server install, but it should also be
- available from the client in "local" (serverless) mode, so that is
- why I mention it here.
-
- --------------------------------------------------------------------
-
- Note: Make sure that the C/370 run time library is available,
- either in the system link list or in the ISPLLIB concatenation,
- before attempting to run GOPHER. See above under customization
- of the GOPHER exec.
-
- ./ ADD NAME=INSTALLS
-
- Directions for Installing the GOPHER MVS Server
-
- where @ is the install prefix from the unload and $ is a system prefix
-
- Summary:
-
- 1. (all users) Customize @.H - GGUSER
- 2. (all users) Customize @.CNTL - ALLOAD
- 3. (all users) Customize @.CNTL - COMPILE
- 4. (all users) Customize @.CNTL - LINKC
- 5. (all users) Submit @.CNTL - ALLOAD ==> $.LOAD, @.OBJ
- 6. (all users) Submit @.CNTL - COMPILE --> @.OBJ(*)
- 7. (all users) Submit @.CNTL - LINKC --> $.LOAD(GG*)
- 8. (REXX users) Submit @.CNTL - LINKX --> $.LOAD(XG*)
- 9. (all users) Install @.ABOUT - * --> $.ABOUT(*)
- 10.(all users) Create access file ... DD:GGACCESS
- 11.(all users) Create startup parameters ... DD:GGPARMS
- 12.(REXX users) Create REXX exec PDS ... DD:GGEXEC
- 13.(REXX users) Install @.CLIST - * --> $.CLIST(*)
- 14.(all users) Create started task JCL --> SYS1.PROCLIB
- 15.(all users) Update TCP/IP profile --> TCPIP.TCPIP.PROFI
-
- System libraries to be updated:
-
- $.LOAD - specified in .CNTL(ALLOAD)
- $.OBJ - specified in .CNTL(ALLOAD)
- $.ABOUT - a new PDS you make yourself, or use the install copy
-
- Assuming you have unloaded all the install PDS's:
-
- 1. Customize the GGUSER header file as shown by the comments therein.
- Note in particular the defines for your TCP/IP and your C compiler.
- There are changes to the linkedit JCL that are related to these.
-
- 2,3,4. Customize the ALLOAD, COMPILE and LINKS JCL members to reflect
- your local conventions. Note: If you intend to place the executable
- into an existing library, you can suppress that part of the ALLOAD JCL.
- The name of the data set created must match across both members.
-
- *********************************************************************
-
- IMPORTANT: If you are running TCP/IP V2R2 or higher on MVS, you must
- change the following library names in the compile and link JCL:
-
- TCPIP.COMMMAC should be changed to TCPIP.SEZACMAC
- TCPIP.COMMTXT should be changed to TCPIP.SEZACMTX
-
- If you are using SNS/TCPAccess, use these library names, or
- whatever names are defined at your installation:
-
- TCPIP.COMMMAC should be changed to SNSTCP.V110.H
- TCPIP.COMMTXT should be changed to SNSTCP.V110.CILIB
-
- If you are using SAS/C, change CEESTART to MAIN in the linkedit
- ENTRY control statement.
-
- *********************************************************************
-
- Note: If you have defined C370V1 in the GGUSER header file, you must
- also include the system linklist load library containing IKJEFF18
- when linking. Otherwise you may delete the line from the linkedit
- JCL that references it.
-
- Note: You need not include the PASCAL libraries or the AMPZMVSB
- module if you are using TCP/IP Version 2 or higher, in which case
- you must also define TCPIPV2 in the GGUSER headerfile.
-
- 5. Submit the ALLOAD JCL to allocate the load library from which the
- executable program will be run, as well as the object library in which
- the compiled object modules will be stored.
-
- 6. Submit the COMPILE JCL to compile all the C sources and create the
- required object modules in the object library built in the above step.
- Note that this compiles all the modules for both the client and the
- server. If you are installing both, you need not repeat this step.
-
- 7. Submit the LINKS JCL to create the executable Gopher load modules
- from the object modules created in the above step. This will create
- or replace the load modules GGSERVER and GGSTASK.
-
- Note: The linkedit must complete with a return code of zero. If not,
- don't use the resultant load module. Check the libraries you specified
- on the link step to see what went wrong.
-
- In the future, if you have to recompile individual modules, you can use
- the same JCL to compile only those modules, and the link will include
- the new modules in the existing executable load module. To do this,
- you must retain the object library built above.
-
- 8. Submit the LINKX JCL to create the auxiliary Gopher load modules
- from the object modules created in the above step. This will create
- or replace load modules named XG..., used by the REXX interface.
-
- 9. Create the "About This Gopher" PDS from the ABOUT PDS. This has
- all the text users should see when they select the "About This Gopher"
- item from the MVS client. It also contains all the documentation you
- need about setting up the client and the server, as well as creating
- menus and REXX execs for use with MVS Gopher. You may have already
- done this as part of the client install.
-
- Note that member MENU contains the line PATH=DD:GGABOUT(ABOUT). This
- works now (it didn't use to), so there is no need to change it as long
- as you have the GGABOUT DD statement in your server JCL pointing to
- your ABOUT PDS (see below).
-
- 10. Create your Gopher access file. See the instructions in the
- "About This Gopher" PDS, member ABOUTSA, for a description of the
- format. A sample member is in member ACCESS of this CNTL PDS.
-
- 11. Create your Gopher startup parameter file. This is not required,
- but may be used to change compiled-in defaults. See the PARMS member
- for a default.
-
- 12. Allocate a PDS to hold Gopher REXX execs. This is required only
- if you plan to use the REXX interface for driver scripts. See the
- TSOHELP exec in the CLIST PDS of the distribution for a sample
- application.
-
- 13. Install all of the execs in the CLIST PDS in the library created
- above. These execs, with the exception of GOPHER and NNMFIUCV,
- are required by the new REXX interface.
-
- 14. Create the MVS Gopher started task JCL from either of the samples
- given in GOPHERD and GOPHERT. The GOPHERT is recommended so that you
- can use REXX execs that issue TSO commands, but you may not want to
- use this for security reasons. Either way, customize liberally.
-
- Started task parameters:
-
- MODULE=GGSERVER the Gopher server load module in STEPLIB
- STEPLIB='GOPHER.LOAD' the load library containing the above
- EXECLIB='GOPHER.EXEC' the PDS containing server REXX execs
- ACCESS='GOPHER.ACCESS' the installation access file (sequential)
- ABOUT='GOPHER.ABOUT' the PDS containing "About This Gopher" info
- MENU='GOPHER.MENU' the initial gopher menu (sequential)
- PARMS='GOPHER.PARMS' the server startup file (sequential)
- GPARM= the server EXEC parms (e.g. -d for debug)
-
- Note: if you specify GPARM='-D', a GGDEBUG DD must be included.
-
- You are strongly recommended to create 2 started tasks: one for
- non-REXX requests with MTFTASKS set to 8, and one for REXX requests
- with MTFTASKS set to 1 (because of TSO/E multitasking bugs).
- Give each a different port number in the GGPARMS configuration file
- allocated to it. See sample below.
-
- 15. Add the name of the Gopher server started task (the name as it
- appears in SYS1.PROCLIB, not necessarily "GOPHER") to the MVS TCPIP
- profile data set (or have your MVS TCP/IP system programmer do it).
- In the examples below, let's say you've called it GOPHSRV. Add this
- in 2 places:
-
- (a) under AUTOLOG, so that TCP/IP will start the Gopher server
- automatically (a la inetd for unix) when a client connects.
- Just add the name to the list (e.g. GOPHSRV).
-
- (b) under PORT, so nobody can spoof the Gopher port. The format
- here is: 70 TCP GOPHSRV
-
- Repeat both for whatever number of Gopher server started tasks you
- create (with different port numbers).
-
- --------------------------------------------------------------------
-
- Note: Make sure that the C/370 run time library is available,
- either in the system link list or in the STEPLIB concatenation,
- before attempting to run GOPHER.
-
- --------------------------------------------------------------------
-
- Following is an example of how to define two Gopher servers.
-
- 'SYS1.PROCLIB(GOPHSRV)' - the primary gopher server (port 70)
- will not run any REXX execs
-
- //GOPHERD PROC MODULE=GGSERVER,
- // STEPLIB='GOPHER.LOAD',
- // ACCESS='GOPHER.ACCESS(ACCESS)',
- // PARMS='GOPHER.ACCESS(PARMS)',
- // MENU='GOPHER.ACCESS(MENU)',
- // STDERR='*',
- // STDOUT='*',
- // GPARM=
- //*
- //GOPHERD EXEC PGM=&MODULE,PARM='&GPARM'
- //STEPLIB DD DISP=SHR,DSN=&STEPLIB
- //SYSERR DD SYSOUT=&STDERR
- //SYSPRINT DD SYSOUT=&STDOUT
- //SYSIN DD DUMMY
- //GGDEBUG DD SYSOUT=*
- //GGACCESS DD DISP=SHR,DSN=&ACCESS
- //GGPARMS DD DISP=SHR,DSN=&PARMS
- //GGGOPHER DD DISP=SHR,DSN=&MENU
-
- 'SYS1.PROCLIB(GOPHSRV2)' - the secondary gopher server (port 1570)
- will run REXX execs
-
- //GOPHERD2 PROC MODULE=GGSERVER,
- // STEPLIB='GOPHER.LOAD',
- // EXECLIB='GOPHER.EXEC',
- // ACCESS='GOPHER.ACCESS(ACCESS2)',
- // PARMS='GOPHER.ACCESS(PARMS2)',
- // MENU='GOPHER.ACCESS(MENU2)',
- // VIO=VIO,
- // STDERR='*',
- // STDOUT='*',
- // GPARM=
- //*
- //GOPHERD2 EXEC PGM=IKJEFT01,DYNAMNBR=128, PARM='&MODULE &GPARM'
- //STEPLIB DD DISP=SHR,DSN=&STEPLIB
- //SYSEXEC DD DISP=SHR,DSN=&EXECLIB /* needed for %-invoked execs */
- //GGEXEC DD DISP=SHR,DSN=&EXECLIB
- //SYSTSPRT DD UNIT=&VIO,SPACE=(TRK,(100,100)),RECFM=VBA,LRECL=255
- //SYSERR DD SYSOUT=&STDERR
- //SYSPRINT DD SYSOUT=&STDOUT
- //SYSTSIN DD DUMMY
- //SYSIN DD DUMMY
- //GGDEBUG DD SYSOUT=*
- //GGACCESS DD DISP=SHR,DSN=&ACCESS
- //GGPARMS DD DISP=SHR,DSN=&PARMS
- //GGGOPHER DD DISP=SHR,DSN=&MENU
-
- 'GOPHER.ACCESS(PARMS)' - startup parameters used by the primary server
-
- mtftasks 8 (this is the default)
- port 70 (this is the default too)
-
- 'GOPHER.ACCESS(PARMS2)'- startup parameters used by the secondary server
-
- mtftasks 1 Force single threading to prevent TSO burpages
- port 1570 Must be different from primary server's port
-
- -----------------------------------------------------------------------
-
- I have not included members ACCESS, ACCESS2, MENU and MENU2, but you
- will find samples elsewhere in this distribution. ACCESS and ACCESS2
- can be the same, except that you don't need the REXX execs to be in
- ACCESS since ACCESS can't run REXX execs. MENU and MENU2 should be
- the same, since you may want to configure various Gopher clients
- on other machines to try both MVS servers, but it's up to you.
-
- ./ ADD NAME=LINKC
- //JOBNAME JOB ACCOUNT,'NAME'
- //* */
- //* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 */
- //* */
- //* This software is provided on an "AS IS" basis. All warranties, */
- //* including the implied warranties of merchantability and fitness, */
- //* are expressly denied. */
- //* */
- //* Provided this copyright notice is included, this software may */
- //* be freely distributed and not offered for sale. */
- //* */
- //* Changes or modifications may be made and used only by the maker */
- //* of same, and not further distributed. Such modifications should */
- //* be mailed to the author for consideration for addition to the */
- //* software and incorporation in subsequent releases. */
- //* */
- //*********************************************************************
- //*
- //* Linkedit an executable Gopher load module.
- //*
- //GGLINK PROC LOADLIB='GOPHER.LOAD', Executable load library
- // OBJLIB='GOPHER.INSTALL.OBJ', Input object PDS
- // PLIBASE='SYS1.PLIBASE', PL/1 link library
- // EDCBASE='SYS1.SEDCBASE', C/370 link library
- // IBMBASE='SYS1.SIBMBASE', PL/1+C common library
- // COMMTXT='TCPIP.COMMTXT', TCP/IP link library
- // VIOUNIT=VIO, Temporary disk unit
- // OUTCLAS='*', SYSOUT class
- // LPARMS='LIST,LET,MAP', Linkedit parameters
- // TEST=TEST TEST or NOTEST
- //*
- //LKED EXEC PGM=IEWL,PARM='AMODE(31),RMODE(ANY),&TEST,&LPARMS'
- //SYSPRINT DD SYSOUT=&OUTCLAS
- //DUMMYDD DD DUMMY,DSN=&OBJLIB needed to prevent JCL errors
- //SYSLIB DD DISP=SHR,DSN=&PLIBASE
- // DD DISP=SHR,DSN=&EDCBASE
- // DD DISP=SHR,DSN=&IBMBASE
- // DD DISP=SHR,DSN=&COMMTXT
- //SYSLMOD DD DISP=SHR,DSN=&LOADLIB
- //SYSUT1 DD DSN=&&SYSUT1,UNIT=&VIOUNIT,DISP=(NEW,DELETE),
- // SPACE=(32000,(30,30))
- //*
- // PEND
- //*
- //*
- //* Link GOPHER load module. Like SMP/E, expect return code 8 when
- //* doing this from scratch. Additional one-or-two-module links
- //* will just replace the corresponding parts of the load module.
- //*
- //GGLINK EXEC GGLINK
- //LKED.SYSLIN DD DISP=SHR,DSN=&OBJLIB(GGACCES)
- // DD DISP=SHR,DSN=&OBJLIB(GGALLOC)
- // DD DISP=SHR,DSN=&OBJLIB(GGASVC)
- // DD DISP=SHR,DSN=&OBJLIB(GGBARF)
- // DD DISP=SHR,DSN=&OBJLIB(GGBIN)
- // DD DISP=SHR,DSN=&OBJLIB(GGBKMGR)
- // DD DISP=SHR,DSN=&OBJLIB(GGCLIEN)
- // DD DISP=SHR,DSN=&OBJLIB(GGCLRTX)
- // DD DISP=SHR,DSN=&OBJLIB(GGCONN)
- // DD DISP=SHR,DSN=&OBJLIB(GGCSO)
- // DD DISP=SHR,DSN=&OBJLIB(GGDBM)
- // DD DISP=SHR,DSN=&OBJLIB(GGDFAIL)
- // DD DISP=SHR,DSN=&OBJLIB(GGDIR)
- // DD DISP=SHR,DSN=&OBJLIB(GGDISC)
- // DD DISP=SHR,DSN=&OBJLIB(GGDISPL)
- // DD DISP=SHR,DSN=&OBJLIB(GGDSOPT)
- // DD DISP=SHR,DSN=&OBJLIB(GGDUMP)
- // DD DISP=SHR,DSN=&OBJLIB(GGESRVR)
- // DD DISP=SHR,DSN=&OBJLIB(GGFREEM)
- // DD DISP=SHR,DSN=&OBJLIB(GGFTP)
- // DD DISP=SHR,DSN=&OBJLIB(GGGETDS)
- // DD DISP=SHR,DSN=&OBJLIB(GGGETM)
- // DD DISP=SHR,DSN=&OBJLIB(GGGOFOR)
- // DD DISP=SHR,DSN=&OBJLIB(GGGSRVL)
- // DD DISP=SHR,DSN=&OBJLIB(GGIERR)
- // DD DISP=SHR,DSN=&OBJLIB(GGIGET)
- // DD DISP=SHR,DSN=&OBJLIB(GGINFO)
- // DD DISP=SHR,DSN=&OBJLIB(GGISPF)
- // DD DISP=SHR,DSN=&OBJLIB(GGIVGET)
- // DD DISP=SHR,DSN=&OBJLIB(GGIVPUT)
- // DD DISP=SHR,DSN=&OBJLIB(GGMENU)
- // DD DISP=SHR,DSN=&OBJLIB(GGMTFER)
- // DD DISP=SHR,DSN=&OBJLIB(GGOUTS)
- // DD DISP=SHR,DSN=&OBJLIB(GGOUTTX)
- // DD DISP=SHR,DSN=&OBJLIB(GGPMSG)
- // DD DISP=SHR,DSN=&OBJLIB(GGPROC)
- // DD DISP=SHR,DSN=&OBJLIB(GGREXX)
- // DD DISP=SHR,DSN=&OBJLIB(GGSLEEP)
- // DD DISP=SHR,DSN=&OBJLIB(GGSOCKT)
- // DD DISP=SHR,DSN=&OBJLIB(GGSOPT)
- // DD DISP=SHR,DSN=&OBJLIB(GGTEMP)
- // DD DISP=SHR,DSN=&OBJLIB(GGTNET)
- // DD DISP=SHR,DSN=&OBJLIB(GGTSO)
- // DD DISP=SHR,DSN=&OBJLIB(GGTYPE)
- // DD DISP=SHR,DSN=&OBJLIB(GGUNALC)
- // DD DISP=SHR,DSN=&OBJLIB(GGVIEW)
- // DD DISP=SHR,DSN=&OBJLIB(GGVTX)
- // DD DISP=SHR,DSN=&OBJLIB(GGWAIS)
- // DD DISP=SHR,DSN=&OBJLIB(GGWHOIS)
- // DD DISP=SHR,DSN=&OBJLIB(GGWTO)
- // DD DISP=SHR,DSN=&OBJLIB(GGXTX)
- // DD *
- ENTRY CEESTART
- NAME GGCLIENT(R)
- /*
- ./ ADD NAME=LINKS
- //JOBNAME JOB ACCOUNT,'NAME'
- //* */
- //* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 */
- //* */
- //* This software is provided on an "AS IS" basis. All warranties, */
- //* including the implied warranties of merchantability and fitness, */
- //* are expressly denied. */
- //* */
- //* Provided this copyright notice is included, this software may */
- //* be freely distributed and not offered for sale. */
- //* */
- //* Changes or modifications may be made and used only by the maker */
- //* of same, and not further distributed. Such modifications should */
- //* be mailed to the author for consideration for addition to the */
- //* software and incorporation in subsequent releases. */
- //* */
- //*********************************************************************
- //*
- //* Linkedit an executable Gopher load module.
- //*
- //GGLINK PROC LOADLIB='GOPHER.LOAD', Executable load library
- // OBJLIB='GOPHER.INSTALL.OBJ', Input object PDS
- // PLIBASE='SYS1.PLIBASE', PL/1 link library
- // EDCBASE='SYS1.SEDCBASE', C/370 link library
- // IBMBASE='SYS1.SIBMBASE', PL/1+C common library
- // COMMTXT='TCPIP.COMMTXT', TCP/IP link library
- // VIOUNIT=VIO, Temporary disk unit
- // OUTCLAS='*', SYSOUT class
- // LPARMS='LIST,LET,MAP', Linkedit parameters
- // TEST=TEST TEST or NOTEST
- //*
- //LKED EXEC PGM=IEWL,PARM='AMODE(31),RMODE(ANY),&TEST,&LPARMS'
- //SYSPRINT DD SYSOUT=&OUTCLAS
- //DUMMYDD DD DUMMY,DSN=&OBJLIB needed to prevent JCL errors
- //SYSLIB DD DISP=SHR,DSN=&PLIBASE
- // DD DISP=SHR,DSN=&EDCBASE
- // DD DISP=SHR,DSN=&IBMBASE
- // DD DISP=SHR,DSN=&COMMTXT
- //SYSLMOD DD DISP=SHR,DSN=&LOADLIB
- //SYSUT1 DD DSN=&&SYSUT1,UNIT=&VIOUNIT,DISP=(NEW,DELETE),
- // SPACE=(32000,(30,30))
- //*
- // PEND
- //*
- //* Link GOPHER server subtask module.
- //*
- //GGLINK EXEC GGLINK
- //LKED.SYSLIN DD DISP=SHR,DSN=&OBJLIB(GGSTASK)
- // DD DISP=SHR,DSN=&OBJLIB(GGACCES)
- // DD DISP=SHR,DSN=&OBJLIB(GGALLOC)
- // DD DISP=SHR,DSN=&OBJLIB(GGASVC)
- // DD DISP=SHR,DSN=&OBJLIB(GGBARF)
- // DD DISP=SHR,DSN=&OBJLIB(GGDFAIL)
- // DD DISP=SHR,DSN=&OBJLIB(GGDUMP)
- // DD DISP=SHR,DSN=&OBJLIB(GGFREEM)
- // DD DISP=SHR,DSN=&OBJLIB(GGFTP)
- // DD DISP=SHR,DSN=&OBJLIB(GGGETM)
- // DD DISP=SHR,DSN=&OBJLIB(GGGSRVL)
- // DD DISP=SHR,DSN=&OBJLIB(GGIERR)
- // DD DISP=SHR,DSN=&OBJLIB(GGISPF)
- // DD DISP=SHR,DSN=&OBJLIB(GGIVPUT)
- // DD DISP=SHR,DSN=&OBJLIB(GGOUTS)
- // DD DISP=SHR,DSN=&OBJLIB(GGPMSG)
- // DD DISP=SHR,DSN=&OBJLIB(GGPROC)
- // DD DISP=SHR,DSN=&OBJLIB(GGREXX)
- // DD DISP=SHR,DSN=&OBJLIB(GGSOCKT)
- // DD DISP=SHR,DSN=&OBJLIB(GGTEMP)
- // DD DISP=SHR,DSN=&OBJLIB(GGTSO)
- // DD DISP=SHR,DSN=&OBJLIB(GGTYPE)
- // DD DISP=SHR,DSN=&OBJLIB(GGUNALC)
- // DD DISP=SHR,DSN=&OBJLIB(GGWTO)
- // DD *
- INCLUDE SYSLIB(IUCVFORC)
- INCLUDE SYSLIB(EDCMTFS)
- ENTRY CEESTART
- NAME GGSTASK(R)
- /*
- //*
- //* Link GOPHER server main module.
- //*
- //GGLINKS EXEC GGLINK
- //LKED.SYSLIN DD DISP=SHR,DSN=&OBJLIB(GGSERVE)
- // DD DISP=SHR,DSN=&OBJLIB(GGACCES)
- // DD DISP=SHR,DSN=&OBJLIB(GGFREEM)
- // DD DISP=SHR,DSN=&OBJLIB(GGGETM)
- // DD DISP=SHR,DSN=&OBJLIB(GGMTFER)
- // DD *
- ENTRY CEESTART
- NAME GGSERVER(R)
- /*
- ./ ADD NAME=LINKX
- //JOBNAME JOB ACCOUNT,'NAME'
- //* */
- //* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 */
- //* */
- //* This software is provided on an "AS IS" basis. All warranties, */
- //* including the implied warranties of merchantability and fitness, */
- //* are expressly denied. */
- //* */
- //* Provided this copyright notice is included, this software may */
- //* be freely distributed and not offered for sale. */
- //* */
- //* Changes or modifications may be made and used only by the maker */
- //* of same, and not further distributed. Such modifications should */
- //* be mailed to the author for consideration for addition to the */
- //* software and incorporation in subsequent releases. */
- //* */
- //*********************************************************************
- //*
- //* Linkedit auxiliary Gopher executables.
- //*
- //GGLINK PROC LOADLIB='GOPHER.LOAD', Executable load library
- // OBJLIB='GOPHER.INSTALL.OBJ', Input object PDS
- // PLIBASE='SYS1.PLIBASE', PL/1 link library
- // EDCBASE='SYS1.SEDCBASE', C/370 link library
- // IBMBASE='SYS1.SIBMBASE', PL/1+C common library
- // EDCSPC='SYS1.SEDCSPC', C/370 sysprog library
- // VIOUNIT=VIO, Temporary disk unit
- // OUTCLAS='*', SYSOUT class
- // LPARMS='LIST,LET,MAP', Linkedit parameters
- // TEST=TEST TEST or NOTEST
- //*
- //LKED EXEC PGM=IEWL,PARM='AMODE(31),RMODE(ANY),&TEST,&LPARMS'
- //SYSPRINT DD SYSOUT=&OUTCLAS
- //DUMMYDD DD DUMMY,DSN=&OBJLIB needed to prevent JCL errors
- //SYSLIB DD DISP=SHR,DSN=&EDCSPC
- // DD DISP=SHR,DSN=&PLIBASE
- // DD DISP=SHR,DSN=&EDCBASE
- // DD DISP=SHR,DSN=&IBMBASE
- //SYSLMOD DD DISP=SHR,DSN=&LOADLIB
- //SYSUT1 DD DSN=&&SYSUT1,UNIT=&VIOUNIT,DISP=(NEW,DELETE),
- // SPACE=(32000,(30,30))
- //*
- // PEND
- //*
- //* Link GOPHER client and server auxiliary modules.
- //*
- //XGALLOC EXEC GGLINK
- //LKED.SYSLIN DD DISP=SHR,DSN=&OBJLIB(XGALLOC)
- // DD DISP=SHR,DSN=&OBJLIB(GGASVC)
- // DD *
- ENTRY XGALLOC
- NAME XGALLOC(R)
- /*
- //XGSLEEP EXEC GGLINK
- //LKED.SYSLIN DD DISP=SHR,DSN=&OBJLIB(XGSLEEP)
- // DD DISP=SHR,DSN=&OBJLIB(GGSLEEP)
- // DD DISP=SHR,DSN=&OBJLIB(GGASVC)
- // DD *
- ENTRY CEESTART
- NAME XGSLEEP(R)
- /*
- //XGWTO EXEC GGLINK
- //LKED.SYSLIN DD DISP=SHR,DSN=&OBJLIB(XGWTO)
- // DD DISP=SHR,DSN=&OBJLIB(GGWTO)
- // DD DISP=SHR,DSN=&OBJLIB(GGASVC)
- // DD *
- ENTRY CEESTART
- NAME XGWTO(R)
- /*
- ./ ADD NAME=MENU
- gopher_menu
-
- TYPE=FILE
- NAME=About This Gopher
- PATH=DD:GGABOUT(ABOUT)
- HOST=+
- END
-
- TYPE=FILE
- NAME=TSO HELP (Sample Illustrating the REXX Interface)
- PATH=EXEC:TSOHELP
- HOST=+
- END
-
- TYPE=DIRECTORY
- NAME=Library/Information Services
- PATH=SYS0008.GOPHER.LIBRARY(LIBRS)
- HOST=MVS.UDEL.EDU
- END
-
- TYPE=TELNET
- NAME=UDINFO - University of Delaware Information
- HOST=UDINFO.UDEL.EDU
- END
-
- TYPE=DIRECTORY
- NAME=Network and System Services Computer Systems
- PATH=SYS0008.GOPHER.DIR(UDTELNET)
- HOST=MVS.UDEL.EDU
- END
-
- TYPE=DIRECTORY
- NAME=Weather Across the Country
- PATH=1/Weather
- HOST=mermaid.micro.umn.edu
- PORT=150
- END
-
- TYPE=DIRECTORY
- NAME=Other Gopher and Information Servers
- PATH=1/Other Gopher and Information Servers
- HOST=gopher.micro.umn.edu
- END
-
- TYPE=DIRECTORY
- NAME=How to use BITNET LISTSERV Servers
- PATH=SYS0008.GOPHER.DIR(LISTSERV)
- HOST=MVS.UDEL.EDU
- END
-
- TYPE=DIRECTORY
- NAME=University of Delaware Newspapers
- PATH=SYS0008.GOPHER.DIR(PAPERS)
- HOST=MVS.UDEL.EDU
- END
-
- /*
- ./ ADD NAME=PARMS
- !
- ! MVS Gopher Sample Startup Parameter File
- !
- ! All entries in this file have the format: variable value comments
- !
- ! These are the possible values and their default settings:
- !
- ! mtftasks 1 Number of concurrent subtasks to handle client requests
- ! port 70 The TCP port number by which clients connect
- ! qlength 20 Queue length for TCP server listen function
- ! timeout 60 Connection timeout specified when socket is closed
- ! domain .DRAPER.COM The suffix to be appende to bald host names
-
- mtftasks 1 Number of concurrent subtasks to handle client requests
- port 70 The TCP port number by which clients connect
- qlength 20 Queue length for TCP subtask creation
- timeout 60 Connection timeout specified when socket is closed
-
- ./ ADD NAME=SECURE
- The following discussion is included by permission of the participants.
-
- From: SEB1525@MVS.draper.com (Steve Bacher)
- Subject: Secure Rexx?
- Organization: Draper Laboratory
- Date: Fri, 19 Nov 1993 16:13:00 GMT
-
- Has anyone given any thought to what would be needed to evaluate the
- "security" of REXX?
-
- I'm thinking of what you'd have to do to prove that it was OK to have
- a REXX script running behind an anonymous FTP or gopher server, for
- example. We know that commands like vi and utilities like PostScript
- are questionable because they provide shell escapes. What could you
- say about a REXX script on such a system?
-
- To start, I'd suggest that you would want to disable the INTERPRET
- statement, so that a remote user could not cause a REXX exec to
- invoke arbitrary code. You might also want to restrict the ADDRESS
- instruction, perhaps limiting it to a set of known address environments.
-
- Any other ideas? Apologies if this question is somewhat Unix-centric.
-
-
- --
- Steve Bacher (Batchman) Draper Laboratory
- Internet: seb@draper.com Cambridge, MA, USA
-
-
- Date: Fri, 19 Nov 1993 13:56:11 -0500
- From: "Stephen E. Bacher" <seb@DRAPER.COM>
- Subject: Re: Secure Rexx?
-
- I would rephrase the question "Is a given program written in
- language X secure?" The answer can be one of "yes", "no", or
- "cannot be determined". Only programs that returned answer
- number one would be eligible for secure environments.
-
- Keep in mind that security is a relative term. Since we cannot
- prove beyond the shadow of a doubt that something is 100% impregnable,.
- one must adopt a "reasonable person" approach. Just as you wouldn't
- protect your house with the same arsenal as is used to protect our
- nuclear launchers.
-
- What I mean is that if you know that if you connect to a gopher server
- at foo.bar.edu, say, and you know that if you pass it a selector string
- of "exec:open-sesame:some-rexx-script", the server will execute the
- script some-rexx-script with a parameter of open-sesame with the
- privileges of the gopher daemon at foo.bar.edu. Depending on the
- powers of that daemon, it could go off and execute a command that
- updated your college transcript, or something. That is kind of
- farfetched, and suggests that the gopher was not set up very securely
- in and of itself, but there are all kinds of possibilities.
-
- One thing that a gopher daemon MIGHT be able to do is to update its
- own gopher menu tree. That could be a risk.
-
- Note that the script might not even be one set up by the gopher guys.
- Of course, we'll cover that particular hole. Note that I don't want
- to go into more detail about just how much security is theirs and
- how much is, or will be, ours - there will be time for that when we
- release our mods to the UMn gopher server (at least I hope we do).
-
-
-
- From: Anders Christensen <anders@lise.unit.no>
- Date: Tue, 23 Nov 1993 22:04:23 +0100
- To: "Stephen E. Bacher" <seb@draper.com>
- Subject: Re: Secure Rexx?
-
-
- > I am specifically concerned about using REXX scripts in a server
- > environment where they will be in the role of delivering publicly
- > available information. Any user could pass a request to have the
- > server run that REXX exec, so it is imperative that what the exec
- > can do be constrained.
-
- I'd say that it's somewhat impossible to have a secure Rexx script,
- the reason is this: In addition to INTERPRET you would have to disable
- several other constructs:
-
- 1) The ADDRESS keyword instruction and commands should be disabled. As
- long as one can do things like:
-
- address system 'echo' var '>/tmp/foo.rexx; rexx /tmp/foo.rexx'
-
- then ADDRESS is just as insecure as INTERPRET.
-
- 2) For language level 3.50 and above, LINEOUT() and CHAROUT() should
- be disabled. Consider the possibility that the program is fooled
- to run code writing to files related to security (.rhosts,
- .forward, .login, etc). That could easily be the first step of an
- attack at the account. Besides:
-
- lineout('myfile',var); say 'myfile'()
-
- is just as insecure as INTERPRET.
-
- 3) There are also some files which should not be readable for the
- whole world. Security is related to files that contain keys for
- encryption (e.g. .xauthority). Thus, maybe LINEIN() and CHARIN()
- should be restricted too.
-
- This results in a Rexx interpreter that cannot execute commands, or
- read or write files. Such a mode is of very limited value. There may
- be other things to disable too:
-
- 4) SAA REXX contains rxfuncadd() and friends in order to dynamically
- load code into the intepreter. It provides lots of 'interesting'
- possibilties.
-
- 5) External functions should perhaps be disabled. Although you can
- verify the contents of the external function like you verify the
- contents of the main program, you cannot enable external functions
- that are not Rexx scripts.
-
- 6) Most implementations contains many extra builtin functions, some
- which may be used as security backdoors. Just consider what can be
- done with the DIAG() bifs under CMS. In the same manner, you'd
- have to disable OPTIONS, since it too, is able to perform random
- operations, depending only on the implementation of the
- interpreter.
-
- 7) The VALUE() bif can be dangerous when used with it's third
- parameter, since under some implementations it can be used to set
- environment variables. Suppose you have a 'secure' command, but
- the user is able to set PATH (under Unix) ...
-
- 8) Interactive tracing ... really lots of interesting possiblities!
- (And remember to disable TRACE() too!)
-
- 9) You have to insulate the stack from effects done by the program.
- Suppose the user just pushes commands to the stack and exits. Most
- Unix version would not suffer from this, but CMS could probably be
- fooled.
-
- I believe that the resulting interpreter would be fairly useless. The
- clue is probably to write secure _scripts_, rather than secure
- _interpreters_; and the main features are:
-
- 1) Never run any external functions or commands that might be
- compromised.
-
- 2) Check (and double-check) the format and contents of all data read
- from external sources, like files, the keyboard, parameter- and
- option-values, or the network.
-
- On the other hand, there are several 'features' about Rexx that makes
- me nervous with respect to so-called secure programming, or provable
- programs. Consider the following part of a long Rexx program:
-
- 'test -f /etc/passwd'
- if rc=0 then
- do_something
-
- The do_something part may perfectly well be called also whenever rc
- was something else than zero. Just assume CALL ON HALT, and the
- following code somewhere else:
-
- halt:
- rc = 0 /* or more likely: a command */
- return
-
- Consequently, the value of RC becomes undefined at all clause
- boundaries (strictly speaking). Thus, one can not use CALL ON HALT in
- 'secure' scripts. Another source of constant despair is arithmetic.
- Consider the seemingly good-natured loop (where an evil eternal loop
- may be lurking!):
-
- do i=5 to 15
- say i
- end
-
- How can this loop become non-ending? By setting NUMERIC DIGITS to 1.
- When i has the value 9 and is incremented, it gets the values 1E1.
- When 1E1 is incremented by 1, it becomes 1E1 ... and thus the eternal
- loop. Therefore, if you want to prove a Rexx program, you have to
- guard against all cases where this may happen: either when NUMERIC
- DIGITS is too low, or when the control variable becomes to high.
- Frankly, this is completely impossible to handle.
-
- These are some of the examples I stumbled across when I was writing
- the trip test. ... Rexx is a very strange languages ... :-)
-
- Regards,
- -anders
-
-
- ./ ENDUP
- ?!
- //ABOUT EXEC MDLOAD,BS='6160',TRK1='5',TRK2='1',TO='ABOUT'
- //SYSIN DD DATA,DLM='?!'
- ./ ADD NAME=ABOUT
- gopher_menu
-
- TYPE=FILE
- NAME=What Is Gopher?
- PATH=(ABOUTW)
- HOST=+
- END
-
- TYPE=FILE
- NAME=Gopher FAQ (Frequently Asked Questions) List
- PATH=(FAQ)
- HOST=+
- END
-
- TYPE=DIRECTORY
- NAME=Using The Gopher MVS Client
- PATH=(ABOUTC)
- HOST=+
- END
-
- TYPE=DIRECTORY
- NAME=Administering the Gopher MVS Server
- PATH=(ABOUTS)
- HOST=+
- END
-
-
- ./ ADD NAME=ABOUTC
- gopher_menu
-
- TYPE=FILE
- NAME=Overview - Using Gopher on MVS
- PATH=(ABOUTCO)
- HOST=+
- END
-
- TYPE=FILE
- NAME=Directory Mode - Viewing a Gopher Directory
- PATH=(ABOUTCD)
- HOST=+
- END
-
- TYPE=FILE
- NAME=File Mode - Browsing a Gopher File
- PATH=(ABOUTCF)
- HOST=+
- END
-
- TYPE=FILE
- NAME=Index Mode - Executing a Gopher Query
- PATH=(ABOUTCQ)
- HOST=+
- END
-
- TYPE=DIRECTORY
- NAME=Customizing Your Gopher Startup
- PATH=(ABOUTCS)
- HOST=+
- END
-
- TYPE=FILE
- NAME=MVS Gopher Frequently Asked Questions (FAQ) List
- PATH=(MVSFAQ)
- HOST=+
- END
-
- ./ ADD NAME=ABOUTCD
- Directory Mode - Viewing a Gopher Directory
-
- When you are viewing a Gopher menu (directory), you may perform any
- of the following actions:
-
- * Scroll up and down via the normal ISPF UP and DOWN commands or PFK's
- to view all the items in the menu
-
- * Scroll left and right via the normal ISPF LEFT and RIGHT commands or
- PFK's to be able to read the entirety of long names on the menu
-
- * Type one of the following letters to the left of a menu item and
- press ENTER:
-
- S - Select the item for viewing or processing
- E - Extract the contents of the item to a file
- P - Print the contents of the item to a system printer
- B - Save the entry as a bookmark (in a bookmark file)
- D - Delete this entry from the bookmark file *** not yet supported **
- Q - Display the item as a file, even if it isn't ("Query")
- I - Display the internal Information of the menu item
-
- * Enter one of the following commands on the command line:
-
- MENU - load a data set containing Gopher menu entries (e.g. bookmark)
- OPTions - set client processing options
- QUIT - exit Gopher entirely
-
- or any standard ISPF command.
-
- When you select an item, what happens next depends on the type of the
- item you have selected.
-
- For a File type, you are placed in browse mode on the data.
-
- For a Directory type, you get another Gopher menu (directory).
-
- For an Index type, you see a panel asking you to enter a search string
- of some kind, after which a Gopher menu (directory) of results appears.
-
- For a TELNET type, a telnet session is started, for which you must
- enter a login name at the appropriate time.
-
- For a TN3270 type, a tn3270 session is started, for which you must
- enter a login name at the appropriate time.
-
- For a CSO type, you are placed in a phonebook lookup session.
-
- For a BookManager type, you are placed in BookManager READ/MVS (tm).
-
- For a binary type, you are placed in browse mode on the binary data.
- This is generally not useful, though.
-
- ./ ADD NAME=ABOUTCF
- Browse Mode - Viewing a File in Gopher
-
- When you are viewing a Gopher file, you are placed in "browse mode".
- This is very similar to normal ISPF data set browse, except that:
-
- * In addition to most browse commands, you may issue any of the
- following commands:
-
- EXT or EXTRACT - copy the current contents to a file
- PRT or PRNT - print the current data to SYSOUT.
- BOOK or BOOKMARK - Save the entry as a bookmark (in a bookmark file).
- INFO - Display the internal Information for this item
- OPT or OPTIONs - Set Gopher client processing options
- QUIT - terminates Gopher entirely.
-
- Note that PRT is different from PRINT, which is a built-in ISPF
- command that prints the current physical screen image.
-
- * The following ISPF browse commands are the only ones that are
- ***not*** supported under GOPHER:
-
- HEX
- BROWSE
- SUBMIT
- LOCATE .label
- .<string> (to assign a label)
- FIND P'generic-string'
- DISPLAY CC/NOCC
-
- ./ ADD NAME=ABOUTCO
- The following is modified from Allan Tuchman's XGOPHER help.
-
- Gopher on MVS is an ISPF dialog interface to the Gopher
- information delivery system from the University of Minnesota.
-
- If your Gopher environment has not been customized by the system
- programmer who installed it, Gopher will start up with an initial
- panel asking you to specify the name of the Gopher server host, as
- well as some other fields which you would normally leave alone.
- Otherwise, you will see the main menu of the default Gopher server
- defined at your installation.
-
- Assuming that the top-level path points to a valid Gopher menu,
- the initial display will show the top level directory of
- gopher information available. Selecting an item from this
- list will fetch the contents of a file, subdirectory, or
- other information. The directory display may be updated to
- show the new subdirectory.
-
- To select an item, type "S" in front of it and press ENTER. This
- puts you into ISPF BROWSE mode on the text of the item. You may also
- type "Q" in front of an item to see it in text format even if it is a
- directory. Or you may type "E" in front of it to extract it into a
- file, or "P" to print it - but you may do this more easily via the
- EXTract command or PRT command from within BROWSE.
-
- Type "I" in front of the item to view the internal menu information.
- This is sometimes helpful if you are not sure why you are having
- trouble accessing an item.
-
- Type "B" in front of the item to save it in a bookmark file. You will
- be prompted to supply the name of a bookmark data set; the default is
- GOPHER.BOOKMARK under your TSO prefix. You may retrieve bookmarks at a
- later date by typing "MENU GOPHER.BOOKMARK" - or whatever data set name
- you used - or you can put a pointer to the bookmark data set in your
- private Gopher menu (for which you need to learn how to edit your
- GOPHERRC file).
-
- Some gopher file types are not supported by the current client.
- These will not appear on your menus. Furthermore, you may not
- be permitted to access some items, depending upon the server
- and the host from which you are trying to access them. These
- restrictions do not apply to local mode, where you can access
- anything that you have local permission to read.
-
- The Gopher MVS client is written by Steve Bacher at Draper Laboratory
- (copyright 1992).
-
- ./ ADD NAME=ABOUTCQ
- Index Mode - Executing a Gopher Query
-
- When you select a Gopher "index" or "query" option, you are expected
- to enter some sort of search string. A typical application is a
- phone book lookup, or a keyword search of some archive.
-
- You will see a popup panel (or just a plain panel if you are running
- an old version of ISPF) that asks you to enter a search string. Just
- type it in and press ENTER. What format the string needs to be in
- depends totally on the service that is going to process it.
-
- What you get back is a directory with a list of "hits" or whatever
- is appropriate for the data you requested. This is just like any
- other Gopher directory.
-
- With the original Gopher protocol, there was no mechanism for
- defining an index/query that returned file data immediately.
- MVS Gopher supports an experimental "whois" type that does this.
- However, since it was only spottily implemented by other Gophers,
- and not always the right way (in the humble opinion of the author
- or the MVS client), it is not likely that you will see such an option
- on your Gopher screen.
-
- ./ ADD NAME=ABOUTCS
- gopher_menu
-
- Type=FILE
- Name=Customizing Your Gopher Startup
- Path=(ABOUTCSC)
- Host=+
- End
-
- Type=FILE
- Name=What Happens When You Start Up Gopher
- Path=(ABOUTCSW)
- Host=+
- End
-
- Type=FILE
- Name=Requesting Local (Serverless) Access
- Path=(ABOUTCSL)
- Host=+
- End
-
- Type=FILE
- Name=The GOPHERRC File
- Path=(ABOUTCSR)
- Host=+
- End
-
- Type=FILE
- Name=Defining GOPHER Menus
- Path=(ABOUTCSM)
- Host=+
- End
-
- Type=DIRECTORY
- Name=REXX Exec Interface
- Path=(ABOUTR)
- Host=+
- End
-
- ./ ADD NAME=ABOUTCSC
-
- =======================================================================
-
- Customizing Your Gopher Startup
-
- =======================================================================
-
- When you use the GOPHER client, information about your use of GOPHER
- is stored in a data set called GOPHERRC. If you don't have one,
- GOPHER will create it for you.
-
- Your default startup menu will contain a single item pointing to a
- GOPHER server on your host system, whether such a server is available
- or not. However, you can ask GOPHER to display a different startup
- menu for you. This startup menu may have entries for the GOPHER
- server on the host system and one for your own private (local) data,
- which the GOPHER client accesses without querying a server.
-
- To get GOPHER to set up a different startup menu, you must edit the
- GOPHERRC file. Note that you may set up the GOPHER startup menu to
- include a pointer to your local data - but you have to create that
- local data in order to use it.
-
- Editing the GOPHERRC file should be easy. Just follow the
- instructions in the comments of the file itself. For information
- about the contents of GOPHERRC, see "The GOPHERRC File."
-
- You may also specify a different startup file when you invoke
- the MVS GOPHER client via the INITFILE keyword - e.g.
-
- GOPHER INITFILE(SOME.OTHER.RC)
-
- If the data set does not yet exist, it will be created. You may
- then edit that data set without altering your usual GOPHERRC setup.
-
- ./ ADD NAME=ABOUTCSL
-
- =======================================================================
-
- Requesting Local (Serverless) Access
-
- =======================================================================
-
- The LOCAL operand on the GOPHER command is a convenient way of
- requesting "local" serverless mode. Specify LOCAL on the GOPHER
- command if you want to enter GOPHER in "serverless" mode - i.e.
- start up with your private GOPHER menu. Specifying LOCAL
- accomplishes two things:
-
- (1) It sets the server to "-", meaning local access. Therefore, you
- must also provide a path, either via the PATH operand on the
- GOPHER command or via a "localmenu:" spec in your GOPHERRC file,
- so that GOPHER knows where to look for your private data. The
- path is a data set name, FULLY QUALIFIED WITHOUT QUOTES.
-
- (2) It allows you to use GOPHER even if there are other TCP/IP socket
- applications active elsewhere in your TSO session. However, it
- will not allow you to connect to any GOPHER servers, even if you
- have a local menu item that points to one.
-
- If you do not specify a server and there is no specification in
- your GOPHERRC file for one, then GOPHER will display a startup
- ISPF panel asking you to specify a server name and, optionally,
- a path name. (Don't touch the port number!)
- ./ ADD NAME=ABOUTCSM
-
- =======================================================================
-
- Defining Gopher Menus
-
- =======================================================================
-
- This is a description of how to define GOPHER menus that can be used
- either for your own private data or by the GOPHER server administrator
- on MVS to define publicly accessible data.
-
- Bear in mind that the menu may be used to specify data meaningful to
- a server other than MVS. Therefore, the descriptions here should be
- interpreted in two ways:
-
- (1) how to define MVS-resident information resources
-
- (2) how to request information resources from other GOPHER servers
-
- ------------------------------------------------------------------------
-
- How To Define MVS-Resident Information Resources
-
- The Gopher server (and the Gopher client, in "local" mode) determines
- how to return information to the client via menus. These menus are
- plain MVS data sets with a particular structure.
-
- An MVS gopher menu is a sequential data set or PDS member with the
- following format:
-
- * the first line contains the string GOPHER_MENU
- (in upper, lower or mixed case)
-
- * the rest of the file contains blocks of information like this:
-
- TYPE=type
- NAME=name
- PATH=path
- HOST=host
- PORT=port
- END
-
- For compatibility with earlier versions of the MVS Gopher server,
- the following are also accepted:
-
- DISPLAY= is equivalent to NAME=
- SELECTOR= is equivalent to PATH=
-
- Explanations
-
- TYPE=type
-
- The type of Gopher entity (FILE, DIRECTORY, INDEX, etc.).
- In other words, one of the following:
-
- FILE - the item is an MVS data set with text to be displayed.
- The path name is the file name or a REXX exec spec.
- DIRECTORY - the item is another Gopher directory.
- The path name is the file name or a REXX exec spec.
- INDEX - the item is a full text search item, which means that
- the client will query the user for a search string
- which will be passed to the server along with the
- pathname. For the MVS server. it only makes sense for
- the pathname to be a REXX exec specification. The path
- and the user's string are given to the host, which
- returns a menu of selections. See also WHOIS.
- TELNET - the item is a Telnet server.
- The path name is ignored. The port number should be
- omitted or set to 0, unless an alternate TELNET port
- is required by the server referenced by HOST.
- TN3270 - the item is a TN3270 server. This is like TELNET
- except that it takes you to a full-screen IBM mainframe
- terminal session.
- CSO - the item is a CSO phonebook server. This is a campus
- information protocol that is not an Internet standard,
- but may be available at some universities.
- WHOIS - the item is a "whois" query. This is similar to the
- INDEX type, except that the server returns a file
- rather than a menu. This is not (yet) an official
- part of the Gopher protocol, though it does appear in
- certain (patched) versions of other implementations.
- BINARY - the item is a binary file. Such a file may be browsed
- or copied, but it is probably of little use.
- BOOKMANAGER - the item is a BookManager READ/MVS (tm) document.
-
- NAME=name
-
- The descriptive string that will appear in the Gopher client's
- display of menu selections for this item. Make this as human as
- possible. Case is preserved.
-
- PATH=path
-
- The pathname to be passed to the Gopher server to retrieve the
- item. See below for a fuller description.
-
- HOST=host
-
- The name of the Gopher server host that will process the request.
- See below for a fuller description.
-
- PORT=port
-
- The TCP/IP port to connect to. For Gopher, this should always be
- port 70 (except for a TELNET or TN3270 type, whose port defaults to
- the standard TELNET port if zero or omitted). If this is omitted,
- then the default port number is taken.
-
- END
-
- Formerly required to keep menu entries separate. However, a comment
- line (any line starting with '*', '#' or '!' in the first column)
- will be interpreted as a menu entry separator, so that Gopher menu
- bookmark files may be ported from Unix systems.
-
- More about Path Names
-
- Note that the format of a path depends on which Gopher server is
- going to be processing the entry, as defined by the HOST= field.
- If the entry is going to a different Gopher server, then the
- pathname format depends on that server. For example, a Unix server
- would expect a Unix file name with a slash.
-
- In general, a selector string for an MVS Gopher server has the format:
-
- t/path
-
- where "t" is the one-character Gopher type, and "path" is usually an
- MVS data set name but may be other things, as indicated below.
-
- It may seem redundant to include the type character when the same
- information is in the TYPE= line in the menu entry. But it really
- isn't, because the Gopher server doesn't see the TYPE= stuff when
- a client sends it a request. The "t" character really tells the
- server what format to use when retrieving the data. It is especially
- important when the data must be rerieved in binary rather than text
- In fact, the type does not need to match the TYPE= type. In some
- cases it is best to specify a binary type (9) in the selector string
- along with some other kind of type.
-
- If the selector string does not begin with a type character followed
- by a slash, then the MVS gopher server will make a best guess as to
- what the type of the item is. For data sets, it will look inside and
- return the data set as a Gopher menu if it is an MVS PDS or if it is
- a text file whose first line says "GOPHER_MENU". Otherwise it will
- return it as a text file. It will never return it as a binary file.
-
- Examples:
-
- SYS1.MACLIB(OPEN) - identifies a text file.
- 0/SYS1.MACLIB(OPEN) - also identifies a text file.
- 1/GOPHER.MENUS(THINGS) - identifies a menu.
-
- This is required if you want to serve a binary file:
-
- 9/SYSB.RANDOM.BITS - identifies a binary file.
-
- Gopher has no other way of telling that the data must be
- transmitted in binary format.
-
- To be more specific about the path names for the MVS gopher server:
-
- * A fully qualified MVS data set name, without quotes, identifying
- a sequential text data set or PDS member. If TYPE=FILE, this is
- text. If TYPE=DIRECTORY, this is a gopher menu as described above.
-
- * A fully qualified MVS data set name, without quotes, identifying a
- PDS (no member). This causes the MVS Gopher server to return a
- list of member names of the PDS in Gopher directory format. This
- should be used only with TYPE=DIRECTORY. Member aliases are
- included in the resulting list.
-
- * A member name enclosed in parentheses. This is treated as
- a full PDS member. In other words, the MVS Gopher server will use
- the name of the PDS in which the menu itself was found.
- This allows you to move PDS's full of Gopher menus around without
- having to worry about changing all the path names. This happens
- only when the menu itself is a PDS member and the host is the
- same as the local host (MVS for the server, - for local mode).
- Specifying HOST=+ is recommended for this.
-
- Each member is treated as a Gopher FILE. The NAME field is
- set to the member name. If you want to do anything fancier
- than this, you will have to construct your own Gopher menu.
-
- * A string "DD:ddname" or "DD:ddname(member)", identifying a file by
- MVS ddname a la C/370. Valid with either TYPE=FILE or
- TYPE=DIRECTORY, so the ddname can point to text or a menu.
- However, if the ddname happens to be allocated to a PDS, it does
- NOT work like a directory above - it's just illegal and will
- probably cause lossage.
-
- * A string "EXEC:execname args", which specifies the name of a
- REXX exec to be executed to return the data. Valid with any
- and all types. To learn more about how to make use of this
- feature, please go back to the "About This Gopher" tree and
- read up on using REXX execs with MVS Gopher.
-
- If you are using your own private GOPHER data via local access
- and you want to run REXX execs, you must have a "localexec:"
- line in your GOPHERRC file identifying your REXX exec library.
-
- * A string "FTPn:ftpstuff", which specifies a remote host, a file or
- directory to be fetched via anonymous FTP to that remote host, and
- the type of the file (n) to be returned. This is valid with any
- Gopher type, but will be most useful with the FILE type (n = 0,
- TYPE=0); the DIRECTORY type (n = 1, TYPE=1); the BINARY type (n = 9,
- TYPE=9); the IMAGE type (n = g, TYPE=g); and possibly others.
-
- * A string "FTPVMn:ftpstuff", which is like FTPn except that the remote
- host is a VM/CMS machine running the "FAL" FTP server.
-
- For all of the above...
-
- Note that the HOST= and PORT= must still point to the MVS gopher
- server, which performs the remote FTP for you.
-
- In the PATH= field, an "FTPn:" style selector string may take one
- of the following forms:
-
- ftpn:host
- ftpn:host:path
- ftpn:host:user:path
- ftpn:host:user:pass:path
-
- If path is omitted, then path is the current directory of the remote
- anonymous FTP session.
- If user is omitted, defaults to "anonymous".
- If pass is omitted, defaults to "gopher@localhost.domain.qualifier".
-
- The syntax is defined to let path always be the last item
- just in case the path name contains a colon.
-
- For the VM variants, the directory is a minidisk specification, and
- the file is in the format minidisk/filename.filemode (no filetype).
-
- Examples:
-
- A directory type request...
-
- ftp1:boombox.micro.umn.edu:/pub/gopher/mvs
- ftpvm1:vm1.nodak.edu:powerl
-
- A file type request...
-
- ftp0:some.place.else.com:guest:guestpassword:/blah/README
- ftpvm0:vm1.nodak.edu:powerl/faq3.ann6000
-
- More About Host Names
-
- You may find that some Gopher servers insist on appending the
- network's domain name to local server hostnames. You should check
- with your network gurus to make sure that this will work with your
- TCP/IP host lookup. The MVS server will accept hostnames either
- with or without the domain name appended - this applies to the
- specification of hostnames in the Gopher access table as well -
- but other Gopher servers may not.
-
- Two special cases:
-
- A plus sign (HOST=+) means that the host is the same host as the one
- that is looking at the directory entry - i.e. the server that is
- serving up this menu. The Gopher server simply plugs in its own host
- name at that point. This is NOT part of the Gopher protocol, but
- merely a server hack.
-
- A minus sign (HOST=-) means that access to this item will be in
- "local" (serverless) mode. This is recognized only by the MVS Gopher
- client. It means that the client will do the retrieval itself,
- without asking a server to do it. When you use this type, the port
- number must be 70.
-
- The directory-processing code, when invoked in "local mode", will
- treat HOST=+ as HOST=- since the current host is the local mode
- operation in that case. Therefore, using HOST=+ is recommended
- so that one can port one's local GOPHER menus to the public server
- at some point.
-
- A REXX exec that generates menus dynamically can use - as a hostname,
- but not +.
-
- ------------------------------------------------------------------------
-
- How To Request Information Resources From Other GOPHER Servers
-
- Rather than describe the standard format of a Gopher menu here,
- I recommend that you go to your nearest Unix box and type
-
- man gopherd
-
- That should tell you all you need to know about Unix gopher servers.
- If your gopher server is on some other kind of machine, then go find
- the documentation for that machine's Gopher menus.
-
- The purpose of the above exercise is primarily to determine the format
- of a path name understood by a given Gopher server. Once you know that,
- you can build a Gopher menu the MVS Gopher will understand, according to
- the format described in the top section. Set the host to point to
- the other Gopher server, who will interpret the other items in the menu.
-
- ------------------------------------------------------------------------
-
- Dynamic Generation of GOPHER Menus
-
- If you want to be able to generate a Gopher menu dynamically,
- you can do this via the REXX interface. You also must understand
- the Gopher protocol. A Gopher menu is really a text representation
- of the actual protocol, which goes like this:
-
- filetype -tab- name -tab- path -tab- host -tab- port
-
- where -tab- is the EBCDIC (on MVS) or ASCII (on other box) tab
- character, and filetype is a single character. The filetypes
- supported by the MVS Gopher server are:
-
- 0 - flat file
- 1 - directory
- 2 - CSO
- 3 - error
- 7 - index
- 8 - TELNET
- 9 - binary
- T - TN3270
- w - whois (experimental)
- i - comment (unselectable menu line)
- b - BookManager format
-
- A REXX exec that wants to generate a Gopher menu must output lines
- in this format. For more information, go back to the Gopher tree
- for "About This Gopher" and look up information on the REXX interface.
-
- ./ ADD NAME=ABOUTCSR
-
- =======================================================================
-
- The GOPHERRC File
-
- =======================================================================
-
- When you use the GOPHER client, you need a file called GOPHERRC
- which stores information about your use of GOPHER. If you don't
- have one, GOPHER will create it for you. The file initially
- contains:
-
- the initial path/name/host/port specification, which tells
- GOPHER what to display on startup. By default this is the
- standard GOPHER server info on MVS. However, you can add
- to your GOPHERRC a specification for local GOPHER by
- editing GOPHERRC and activating one of the following:
-
- - the other "initial:" spec which points to your own startup menu,
- overriding the one you'd get otherwise
-
- - the localmenu: and localexec: lines.
-
- - the telnet:, bookmgr: and domain: lines.
-
- localmenu: is equivalent to specifying an alternate initial:
- spec of host=- (dash) and path=localmenu_name. When you use
- the LOCAL operand of the GOPHER command, localmenu: is what
- GOPHER looks for as the pathname if you don't provide one on
- the command.
-
- localexec: is required if you want to use your own library of
- GOPHER rexx execs. This is valid for LOCAL access only.
-
- telnet: is required if you want to use a telnet command other
- than TELNET. For example, UCLA's XTELNET is recommended if
- you have it (and if you don't have it, then get it).
-
- bookmgr: is required if your BookManager READ/MVS command is
- other than "BOOKMGR". Note, however, that whatever command
- you specify must take a BOOK('data-set-name') argument.
-
- domain: is required if your installation hasn't configured
- the Gopher client to reference the correct local domain.
- This may be the case if you are using the object-code-only
- distribution, for example. Normally when GOPHERRC is built
- upon your first use of the GOPHER client, this value should
- be set correctly. There should never be any need to change it,
- assuming that it works properly, which you'll find out right
- away if it doesn't.
-
- Some option defaults may be stored in the GOPHERRC file;
- others are remembered in your ISPF profile.
-
- Note that bookmarks are not stored in your GOPHERRC file.
- They are stored in separate bookmark data sets, whose names
- the client user must specify. Do not attempt to load your
- GOPHERRC file as a bookmark file!
-
- If you have a newly created GOPHERRC file, you can read the
- comments to guide you in customizing the file.
-
- You may also specify a different startup file when you invoke
- the MVS GOPHER client via the INITFILE keyword - e.g.
-
- GOPHER INITFILE(SOME.OTHER.RC)
-
- If the data set does not yet exist, it will be created.
-
- ./ ADD NAME=ABOUTCSW
-
- =======================================================================
-
- What Happens When You Start Up GOPHER?
-
- =======================================================================
-
- What you see when you start up GOPHER depends on what you have
- specified, either on the command line or in the GOPHERRC file.
- In general, command operands override GOPHERRC specifications.
-
- GOPHER does its thing by connecting to a Gopher server somewhere
- on your network. If you do not specify otherwise, this server is
- assumed to be MVS (the host where you are running this client).
- The default GOPHERRC file specifies this as the server.
- The startup menu you see is the one defined by the administrator
- of that server.
-
- You can request a different server or a different startup menu,
- either by modifying the GOPHERRC file or by specifying command
- operands. The SERVER operand tells GOPHER to get a startup menu
- from a different server, and the PATH operand tells GOPHER what
- startup menu to request (the contents of the path depend on what
- server you point to and what it's looking for, but it is typically
- the name of a file on that system that contains a Gopher menu).
-
- You can also use GOPHER to access your own private data by requesting
- "local" (serverless) mode. A server name of a single dash "-" means
- local access. In this case, you must provide a path name so that
- GOPHER knows where to look for your data. The path name is the name
- of a data set containing your GOPHER menu - it must be FULLY QUALIFIED
- AND WITHOUT QUOTES. The path name can be provided either as a command
- operand or in the GOPHERRC file.
- ./ ADD NAME=ABOUTR
- gopher_menu
-
- Type=0
- Name=REXX Interface Overview
- Path=(ABOUTRO)
- Host=+
- Port=+
- End
-
- Type=0
- Name=Specifying Hostname and Port
- Path=(ABOUTRH)
- Host=+
- Port=+
- End
-
- Type=0
- Name=REXX Interface Reference
- Path=(ABOUTRR)
- Host=+
- Port=+
- End
-
- ./ ADD NAME=ABOUTRH
-
- =======================================================================
-
- Specifying the Right Host Name
-
- =======================================================================
-
- Most of the time you will probably want to generate a menu item
- that points back to your MVS host, not some other host. It may
- even redrive your selfsame REXX exec with new arguments. And if
- the exec was invoked in local (serverless) mode, you want the item
- to get driven in the same mode, probably.
-
- The question is - what's the easiest way to identify what
- the "same server" is? One way is to hardcode the server name (e.g.
- "MVS.DRAPER.COM"), but this is not sufficiently general because:
-
- (1) the server name or location may change
- (2) you can't distribute the exec to other Gopher users
- (3) it won't work the same way in "local mode"
-
- So, you need a way to know what the name of your selfsame host is.
- The MVS Gopher server can use HOST=+, but you can't, as that isn't
- part of the Gopher protocol. So what do you do?
-
- You have the same problem with the Gopher port number. You usually
- want it to be the same as the one by which your REXX exec was invoked.
-
- Use the functions ghost() and gport() to return the current host
- name and port number. So in the above code segment, you might have:
-
- parse arg myargs, gopherargs
- host = ghost(gopherargs)
- port = gport(gopherargs)
-
- Note: the functions hostname() and port() are also available for
- compatibility with earlier releases of the MVS Gopher. However, ghost()
- and gport() are recommended. All of them are required to take
- gopherargs as their argument, or else they may not work properly.
-
- Note that a plus sign "+" will not work when creating a hostname for a
- Gopher menu item. The plus sign is a hack interpreted by the Gopher
- server when it sees it on a menu. It is *not* part of the Gopher
- protocol and therefore cannot be sent over.
-
- However, the minus sign "-" will work, as the Gopher client
- in local mode will interpret it at the protocol level
- (which DOES NOT IMPLY THAT IT IS A PART OF THE STANDARD
- GOPHER PROTOCOL, PROPOSED OR OTHERWISE - THIS IS JUST A
- LOCAL HACK MODIFICATION).
-
- More details on the REXX interface are in the REXX Interface Reference.
-
- ./ ADD NAME=ABOUTRO
- =======================================================================
-
- REXX Exec Interface Overview
-
- =======================================================================
-
- You can request the MVS Gopher server to retrieve information
- dynamically by executing a REXX exec. To request this, you define a
- menu entry with a PATH= field that looks like one of these:
-
- PATH=0/EXEC:execname args (to return a "file")
- PATH=1/EXEC:execname args (to return a "menu")
- PATH=7/EXEC:execname args (to do a search and return a "menu")
- PATH=EXEC:execname args (the old style, still supported)
-
- In all of the above, the REXX exec identified by "execname" is
- executed, along with the arguments "args" given. For example:
-
- PATH=0/EXEC:MYEXEC ANY ARGS
-
- will cause the MYEXEC exec to be executed with "ANY ARGS" as the
- single argument string.
-
- If the TYPE is INDEX, the search string submitted by the user will be
- appended to the args separated by a blank. The exec must be able to
- deal with this.
-
- REXX Execs must be in a PDS allocated to DD GGEXEC. This ddname
- needs to be present in the Gopher server's JCL.
-
- Note that you do not need the /* REXX */ comment at the beginning of
- REXX execs used by gopher (though it does not hurt to include it!),
- because they are invoked by the IRXEXEC facility and not the standard
- TSO CLIST/EXEC search.
-
- You can also use the EXEC: interface from the MVS Gopher client in
- "local" (serverless) mode. For local mode, the GOPHER command will
- allocate the GGEXEC file to the REXX exec library specified on the
- "localexec:" line in your GOPHERRC file, if you have activated it.
- Otherwise you will not be able to use REXX execs in local mode.
-
- Now, how does the REXX exec return data to the Gopher server?
-
- First of all, it depends on the TYPE that the exec is expected
- to return, which has nothing to do with HOW the returning is done.
-
- Second of all, it does it using various internal interfaces which
- you don't have to know about or understand. Some REXX functions
- have already been provided for you to use that will do the dirty
- work for you.
-
- So, first let's talk about how the exec returns data, and then
- about what it is expected to return.
-
- How to return data
-
- The REXX exec must return data by writing it to the data stack
- between a call to GOPEN and a call to GCLOSE.
-
- Example:
-
- parse arg myargs, gopherargs
- call gopen gopherargs
- do while more_data_to_get
- some_data = get_some_data()
- if some_data = "" then queue " "
- else queue some_data
- end
- call gclose gopherargs
-
- Note: It is recommended that you not queue any null lines.
- Although this will not result in failure, the null lines are
- likely to disappear for reasons I would rather not go into here.
-
- If the gopher server is run straight batch rather than as a TSO job, then
- you cannot run REXX execs that require a TSO environment.
-
- If the Gopher server is a TSO-in-batch job (i.e. EXEC PGM=IKJEFT01),
- then you can issue TSO commands from the exec. To get the output,
- though, you need to use OUTTRAP around them. The GTSOTRAP routine is
- provided to do this for you. If the command issues TPUTs instead of
- PUTLINEs, though, you are out of luck.
-
- Note that a Gopher server running in TSO mode will almost certainly be a
- single-threading server, to prevent more than one client from running in
- the same TSO environment at the same time.
-
- If you want to run a PL/1 program that writes to SYSPRINT, or a FORTRAN
- or assembler program, etc., you can allocate the SYSPRINT or FT06F001
- or whatever file to a temporary and dump the temporary to the stack.
- The problem with both PL/1 and FORTRAN programs is that, like TSO
- commands, they must be run in a single-threading Gopher server, because
- otherwise you may run into a conflict if two clients try to write to
- the same DDNAME.
-
- If, on the other hand, your program is a C/370 program that writes to
- stdout or stderr, you can avoid this problem by using redirection,
- as in this example using a C program called HELLO:
-
- for stdout:
-
- stdout = grabtemp()
- call gcall "HELLO", args "> DD:"stdout
- call gopen gopherargs
- "EXECIO * DISKR" stdout "(FINIS)"
- call ungrab stdout
- call gclose gopherargs
-
- for stderr:
-
- stderr = grabtemp()
- call gcall "HELLO", args "2> DD:"stderr
- call gopen gopherargs
- "EXECIO * DISKR" stderr "(FINIS)"
- call ungrab stderr
- call gclose gopherargs
-
- For multiple output, use >> instead of > in your parameter list.
-
- Note that the C program must reside in a library allocated to
- STEPLIB in the gopher server JCL. Of course, you can use the TSO
- CALL command if you're using the single-threaded TSO server, but
- then you wouldn't be worrying about this issue anyway.
-
- Recommended JCL for executing the Gopher server may be found
- elsewhere in the installation materials, or your MVS system
- programmer has probably already installed a Gopher server or two in
- 'SYS1.PROCLIB' or the equivalent with the correct allocation.
-
- What it is expected to return
-
- OK - now the good stuff. This depends on the TYPE on the menu entry
- that your exec is trying to fulfill. Some gopher protocol basics:
-
- A Gopher menu is really a text representation of the actual protocol,
- which goes like this:
-
- filetype name -tab- path -tab- host -tab- port
-
- where -tab- is the EBCDIC (on MVS) or ASCII (on other box) tab
- character, and filetype is a single character. The filetypes
- supported by the MVS Gopher server include:
-
- 0 - flat file
- 1 - directory
- 7 - index
-
- There are also other types, including binary types, but you won't be
- able to use those with REXX execs, at least not now.
-
- To generate the equivalent of a Gopher menu, you must output data
- in the above format. Now for the details...
-
- TYPE=FILE
-
- Just return the straight data. Try to avoid null lines because C/370
- believes they don't exist and will throw them away. Change all null
- lines to lines containing one blank as you write them out (you're used
- to doing this if you are queueing output on the stack) and you will
- have no problems.
-
- TYPE=DIRECTORY
-
- You must return lines that fit the gopher protocol format as above.
-
- For example, if you want to generate a Gopher menu on the fly that
- is equivalent to this:
-
- type=file
- name=This is my description
- path=some.gopher.path
- host=sun1.sanjuan.com
- port=70
-
- then you output a line that looks like this:
-
- 0This is my description!some.gopher.path!sun1.sanjuan.com!70
-
- (each ! is really a tab (EBCDIC hex 05) character)
-
- where "0" is the type (file in this example, but would be "1" for
- type=directory, "7" for typeindex, etc.)
-
- Here's the REXX code that might do this:
-
- name = "This is my description"
- path = "some.gopher.path"
- host = "sun1.sanjuan.com"
- port = 70
- tab = '05'x
- queue "0"||name||tab||path||tab||host||tab||port
-
- See "Specifying Hostname and Port" for more information.
-
- ./ ADD NAME=ABOUTRR
- MVS Gopher (Version 3) - New REXX Interface
-
- The REXX interface for the MVS gopher server has been completely
- rewritten. Features:
-
- It is much easier to write REXX execs that work without
- needing arcane facilities.
-
- The right hostname and port are automatically taken care of.
-
- Execs do not require a TSO environment, so they can be run
- from a truly multitasking non-TSO Gopher server.
-
- Here is how it works.
-
- A REXX exec is invoked from a Gopher menu option by defining a
- Gopher menu item something like this:
-
- Type=t (whatever type)
- Name=the name of your option
- Path=n/EXEC:execname parameters
- Host=mvs.draper.com
- Port=pn
-
- where:
-
- t is the type to be asked for by the client
- (0 = text, 1 = menu, 7 =- index, etc.).
-
- n is the type to be returned by the exec
- (0 = text, 1 = menu, 9 = binary, etc.).
- Usually (but not always) this will match "t".
-
- pn is the port number (70 for the primary gopher server,
- 1570 for the secondary, if you follow the recommended
- conventions for two gopher servers).
-
- execname is the name of the exec (1-8 characters). It
- must be a member of the PDS allocated to DDname GGEXEC
- in the gopher server started task JCL.
-
- parameters are arguments, if any, passed to the exec.
-
- For the path name, the n/ part may be omitted for compatibility
- with the old style of REXX exec invocation. The purpose of the
- n/ part is to identify the type: 0/ means return text data,
- 1/ means return a menu, 9/ means return binary data, etc.
- If this is omitted, text data is assumed - of course, if the
- gopher client originally asked for a menu, then the output will
- be assumed to be in gopher menu format.
-
- The REXX exec itself will work like this:
-
- It takes two argument values, which can be parsed thusly:
-
- parse arg rexxargs, gopherargs
-
- "rexxargs" is whatever follows "EXEC:execname" in the
- menu item. For type 7 (index), the search string that the
- client user typed in gets appended to the value in the path,
- separated by a space.
-
- "gopherargs" is a string that contains information needed by
- the exec to communicate with Gopher. You don't need to know
- the format of this, since all you will do is pass it to a
- series of REXX functions that are provided as part of the
- Gopher - REXX interface. These functions must be stored in
- the DDname GGEXEC PDS (you can use concatenated PDS's if you
- like). These functions are:
-
- GCALL
- GCLOSE
- GHOST
- GNOTIFY
- GOPEN
- GPORT
- GRAB
- GRABTEMP
- GREAD
- GTSOTRAP
- UNGRAB
-
- For compatibility with the instructions given in previous
- versions of the MVS gopher, the following functions are
- also provided:
-
- HOSTNAME (obsolete, use GHOST)
- PORT (obsolete, use GPORT)
-
- However, they now take a gopherargs argument:
-
- hostname(gopherargs)
- port(gopherargs)
-
- Installation note: You must be running at least TSO/E 2.3.1
- to use GCALL, and you need to install the XGALLOC program
- in a library allocated to STEPLIB in the gopher server
- started task JCL - this is used by GRAB, GRABTEMP and UNGRAB.
-
- If you cannot use one or more of GCALL or the GRAB family,
- you can still run the REXX interface, but you must use the
- TSO "ALLOCATE", "FREE" and "CALL" commands. That means you
- must run a server that runs IKJEFT01 and single-threads.
-
- GREAD and GTSOTRAP are merely conveniences for the programmer.
- Note that GTSOTRAP by its nature, unlike the others, actually
- requires a TSO environment to be present.
-
- Explanation:
-
- GCALL - call a compiled (assembler, C, etc.) program
- GCLOSE - write out and close GOPHER text output stream
- GHOST - return the hostname of the current menu item
- GNOTIFY - log a write-to-programmer message to syslog
- GOPEN - open GOPHER text output stream
- GRAB - allocate an existing data set
- GRABTEMP - allocate a temporary data set
- GREAD - read contents of a file onto the stack
- GTSOTRAP - direct output of a TSO command onto the stack
- UNGRAB - unallocate a file
-
- Note the routines that write stuff onto the stack, and also the
- fact that there is no "GWRITE" routine. Why? Because the way to
- send Gopher data remains the same as it was in earlier versions:
- you queue it onto the REXX data stack. The difference is that
- you call the GOPEN and GCLOSE routines to manage the stack - you
- do not need to fool around with EXECIO or SYSTSPRT. In fact,
- SYSTSPRT is not even used anymore.
-
- Many of these functions take gopherargs as an argument, because
- gopherargs contains the information they need to function.
-
- Why the funny routines?
-
- Well, for one thing, to make it easier for you to write your REXX
- code. But also to enforce certain things. When you are working in a
- multitasking environment, there are some things that you may be used to
- doing that you cannot do. Chief among them is that you cannot use
- hardcoded or preset ddnames. There may be several gopher execs running
- simultaneously and your execs can blow each other (and gopher) away if
- you do. That is why we provide allocation routines - they generate
- unique ddnames and return them to your exec, and you are supposed to
- use those ddnames and no other.
-
- Also, this frees you from the necessity of having a TSO environment,
- where you cannot use commands like ALLOCATE.
-
- Detailed Descriptions
-
- GCALL - call a compiled (assembler, C, etc.) program
-
- Syntax: call gcall modulename, parameters
-
- Returns: the return code from the specified module
- in REXX variable "RESULT" (as per the REXX "call" statement)
-
- Example: call gcall "IEFBR14", "SIZE=200K"
- say "Return code is" result
-
- GCLOSE - write out and close GOPHER text output stream
-
- Syntax: call gclose gopherargs
-
- Returns: nothing of interest
-
- Example: parse arg foo bar baz , gopherargs
- call gopen gopherargs
- queue "This is some Gopher data."
- queue "This is some more Gopher data."
- call gclose gopherargs
-
- GHOST - return the hostname of the current menu item
-
- Syntax: host = ghost(gopherargs)
-
- Returns: the hostname of the MVS gopher server that invoked you
-
- Example: parse arg foo bar baz , gopherargs
- tab = x'05'
- type = "0"
- name = "Cool Stuff"
- path = "0/EXEC:KOOLS" foo
- host = ghost(gopherargs)
- port = gport(gopherargs)
- queue type || name || tab || path || tab || host || tab || port
-
- GNOTIFY - send a write-to-programmer log message to the system log
-
- Syntax: call gnotify "GGMVSnnn message text"
-
- Returns: nothing
-
- Comments: If you have disabled logging in the server, you probably don't
- want to be using this either.
-
- Example: call gnotify ,
- "GGMVS999 The Gopher server is experiencing grave lossage."
-
- GOPEN - open GOPHER text output stream
-
- Syntax: call gopen gopherargs
-
- Returns: nothing of interest
-
- Example: parse arg foo bar baz , gopherargs
- call gopen gopherargs
- queue "This is some Gopher data."
- queue "This is some more Gopher data."
- call gclose gopherargs
-
- GRAB - allocate an existing data set
-
- Syntax: newddname = grab(datasetname,disposition)
- datasetname is a fully qualified MVS name (quotes optional)
- disposition is one of: SHR OLD MOD NEW
-
- Returns: a unique ddname (null string if allocation failed)
-
- Comments: GRAB stands for "Gopher Resource Allocation in Batch"
-
- Example: infodd = grab("GOPHER.INFO.DATA","SHR")
- if infodd = "" then exit 12 /* fail */
- call gopen gopherargs
- call gread infodd
- call gclose gopherargs
- call ungrab infodd
-
- GRABTEMP - allocate a temporary data set
-
- Syntax: newddname = grabtemp()
-
- Returns: a unique ddname (null string if allocation failed)
-
- Comments: GRABTEMP stands for "Gopher Resource Allocator in Batch to
- Touch Empty Memory Pages"
-
- Example: tempdd = grabtemp()
- if tempdd = "" then exit 12 /* fail */
- "newstack"
- queue "hi there"
- queue "bye"
- queue ""
- "EXECIO * DISKW" tempdd "(FINIS)"
- call ungrab tempdd
-
- GREAD - read contents of a file onto the stack
-
- Syntax: call gread ddname
-
- Returns: nothing of interest
-
- Comments: ddname should have been set by call to GRAB or GRABTEMP first
-
- Example: infodd = grab("GOPHER.INFO.DATA","SHR")
- if infodd = "" then exit 12 /* fail */
- call gopen gopherargs
- call gread infodd
- call gclose gopherargs
- call ungrab infodd
-
- GTSOTRAP - direct output of a TSO command onto the stack
-
- Syntax: call gtsotrap tsocommandstring, gopherargs
-
- Returns: the return code from the TSO command
-
- Comments: TSO environment is required. Note that thisn routine
- does gopen and gclose internally. DO NOT CALL GOPEN
- OR GCLOSE IF YOU USE THIS ROUTINE.
-
- Example: parse arg stuff, gopherargs
- call gtsotrap "LISTD" stuff "M ST", gopherargs
-
- UNGRAB - unallocate a file
-
- Syntax: call ungrab ddname
-
- Returns: return code from dynamic unallocation
-
- Example: infodd = grab("GOPHER.INFO.DATA","SHR")
- if infodd = "" then exit 12 /* fail */
- call gopen gopherargs
- call gread infodd
- call gclose gopherargs
- call ungrab infodd
-
- An Example for You to Play With
-
- This "REXXTEST" gopher menu item allows you to poke around and
- see what is really going on in the REXX world Try it.
-
- TYPE=0
- NAME=Test the REXX Interface on port 70 (MVS Gopher server 1)
- PATH=EXEC:REXXTEST
- HOST=+
- PORT=70
- END
-
- TYPE=0
- NAME=Test the REXX Interface on port 1570 (MVS Gopher server 2)
- PATH=EXEC:REXXTEST
- HOST=+
- PORT=1570
- END
-
- and here is the REXXTEST exec:
-
- /* REXX */
-
- parse arg args, gopherargs
- parse version rexx_version
- parse source rexx_source
-
- call gopen gopherargs
-
- queue "PARSE VERSION returns:" rexx_version
- queue "PARSE SOURCE returns:" rexx_source
- queue "Argument 1 is........." args
- queue "Gopherargs are........" gopherargs
-
- call gclose gopherargs
-
- return
-
- ./ ADD NAME=ABOUTS
- gopher_menu
-
- TYPE=FILE
- NAME=Creating MVS Gopher Menus
- PATH=(ABOUTCSM)
- HOST=+
- END
-
- TYPE=FILE
- NAME=MVS Gopher Access Table
- PATH=(ABOUTSA)
- HOST=+
- END
-
- TYPE=FILE
- NAME=MVS Gopher Startup Parameters
- PATH=(ABOUTSP)
- HOST=+
- END
-
- TYPE=DIRECTORY
- NAME=REXX Exec Interface
- PATH=(ABOUTR)
- HOST=+
- END
-
- ./ ADD NAME=ABOUTSA
-
- Format of entries in the Gopher Access Table
-
- Each entry in the table is a single line containing, in the most
- general sense, a filename followed by a list of hostnames.
-
- The filename (fully qualified, all uppercase, no quotes)
- can be a fully qualified MVS data set name, or a string like
- DD:DDNAME or EXEC:EXECNAME. It can also contain an asterisk
- for a wildcard specification - see below for more details.
-
- The hostnames are names of TCP/IP machines which are authorized to
- access the data. If no host name list is present, all hosts are
- authorized to access the specified filename.
-
- You may specify the same file name more than once, if you need more
- lines to put additional host names on. There is no syntactic
- convention for continuing a long line, so this is how you would do
- it. This allows multiple entries for a path specifying different
- hosts, so the MVS administrator doesn't have to worry about running
- out of room on a line.
-
- Individual PDS members are specified separately. A PDS without
- a member name establishes access only to the PDS directory.
- However, you can use wildcarding to specify access to all members
- of a given PDS: just put an asterisk in place of the member name.
- For example, SYS1.SOME.PDS(*) would define access to all members
- of SYS1.SOME.PDS.
-
- Note that the default directory (DD:GGGOPHER) MUST be in this table.
- You could use this entry to define access to the top-level server.
-
- Also note that in the case of EXECs, the EXEC must live in the
- library allocated to GGEXEC in the Gopher server JCL. (Of course;
- how could it be executed otherwise?)
-
- *** ANY DATA SET REFERENCED BY ANY EXEC IN THAT LIBRARY, AS WELL AS
- *** ANY EXEC INVOKED BY THE FIRST EXEC, IS FULLY ACCESSIBLE TO GOPHER
- *** REGARDLESS OF THIS TABLE! USE THIS TABLE TO GOVERN CONTROL TO
- *** THE EXEC ITSELF!!!
-
- How Wildcards Are Handled
-
- In prior versions of MVS Gopher, the access file was read each time a
- client request came in and the format was limited to:
-
- dsname host1 host2 host3
-
- The file was read until an entry that matched both the path and the
- host was found. If no such entry existed the access was denied. Doing
- it this way also allowed for multiple entries for a path specifying
- different hosts, so the MVS administrator didn't have to worry about
- running out of room on a line.
-
- In V3, the access file contains lines that are read into memory and
- sorted into an appropriate order. The format is:
-
- pathspec hostspec1 hostspec2 hostspec3
-
- "pathspec" may be a wildcard expression. Currently, the only wildcard
- syntax is a single asterisk ("*" character) somewhere in the pathspec.
-
- "hostspecn" is a hostname, as before.
-
- Access Rule Prioritization
-
- Since with wildcards, a path can match more than one rule, with possible
- conflicting results, an algorithm has been established for picking the
- appropriate access rule.
-
- Each rule is given two weight values - a major weight and a minor
- weight. You can see these weights printed out by the server when the
- server is started up.
-
- The major weight is set to the actual length of the pathname in
- characters, excepting wildcard characters. This represents the number
- of explicit characters in the pathspec that matches the target name.
- The minor weight is set to the number of characters preceding the
- asterisk (the entire length of the path if no wildcard). The rules are
- then sorted in descending order of major and minor weight. We will
- refer to this major and minor weight as a "weight-pair".
-
- When a client request comes in, a search is done until a rule is found
- that matches the path - in other words, the highest weight-pair
- associated with a matching rule is found. Then, all the rules with the
- same weight-pair as that rule are tested. If the request matches ANY
- of these rules and succeeds (i.e. one of these rules has both a
- maatching path and a matching host), the access is allowed. If the
- request does not match any of these rules, the access is denied - no
- rules of other weight-pairs are checked.
-
- Consider this example:
-
- foo.bar.baz host0
- foo.*.baz host1 host2 host3
- foo.bar.* host4 host5 host6
- foo.* host7 host8 host9
- *.baz host10 host11 host12
- foo.xxx.* host13 host14 host15
-
- The above rules have the following weights:
-
- Pathname Major Minor
-
- foo.bar.baz 11 11
- foo.bar.* 8 8
- foo.xxx.* 8 8
- foo.*.baz 8 4
- foo.* 4 4
- *.baz 4 0
-
- We've displayed the rules above in the order in which they will be
- searched. They could have been specified in any order in the
- access file. The only time the order in the access file matters
- is for rules of the same weight-pair.
-
- Now, if a client requests to see a file, here's what happens.
-
- If the request is for file foo.bar.baz, the first rule, with weight-pair
- 11-11, matches. This is the obvious case where we have an exact match
- with no wildcards, which always is "best".
-
- So, the only host that can access foo.bar.baz is host0, because there
- is an explicit rule governing it, the "foo.bar.baz" rule, which "wins".
-
- If, on the other hand, the request is for file foo.bar.mumble.baz, all
- except two of the rules apply. "foo.bar.baz" and "foo.xxx.*" do not
- match, but all the other rules do in this case. However, only the
- rules of the "best" weight-pair will apply. Here the highest
- weight-pair among the eligible rules is 8-8, because we have a pathname
- match with "foo.bar.*". Therefore, only rules of weight-pair 8-8 will
- be considered. Since the only rule of weight-pair 8-8 that matches the
- client's requested file name is the "foo.bar.*" rule, the only hosts
- that can access this file are host4, host5, and host6.
-
- Looking at it another way, "foo.bar.*" is a "better" match than
- "foo.*.baz", "foo.*" or "*.baz", even though they all potentially
- match, so we apply the "foo.bar.*" rule and do whatever it says.
-
- Now, consider a request for foo.bar.mumble. That could match any of
- "foo.bar.*" or "foo.*" - but, as we have seen, "foo.bar.*" is a more
- powerful match, as proven by its weight-pair. Therefore,
- foo.bar.mumble can be accessed by host4, host5 and host6. Note that
- host7, host8 and host9 cannot access it, even though it would seem to
- match the "foo.*" rule, because the "foo.bar.*" rule takes precedence.
-
- In cases where more than one rule with a given weight-pair should
- match a given file, the first one that finds a matching host wins,
- as with Gopher v2. This allows you to continue to specify the same
- file name with multiple host strings.
-
- ./ ADD NAME=ABOUTSP
-
- MVS Gopher Startup Parameter File
-
- The Gopher server started task may contain a DD statement pointing
- to DDname GGPARMS. If so, this file contains startup parameters
- for that invocation of the server. If such a file does not exist,
- the defaults (as in the header file GGUSER) are used.
-
- One possible use of this feature is to have more than one MVS Gopher
- server running, with different port numbers. This may prevent some
- bottlenecking situations.
-
- All entries in this file have the format: variable value comments
-
- These are the possible values and their default settings:
-
- mtftasks 1 Number of concurrent subtasks to handle client requests
- port 70 The TCP port number by which clients connect
- qlength 20 Queue length for TCP server listen function
- timeout 60 Connection timeout specified when socket is closed
- domain .DRAPER.COM The suffix to be appende to bald host names
-
- You may notice that the TELNET command may be set in this file too.
- That was probably a misunderstanding, as it's the client, not the
- server, that controls how telnets are to be done.
-
- ./ ADD NAME=ABOUTW
- What is Gopher?
-
- For more information, read the FAQ, posted to USENET newsgroups
- comp.infosystems.gopher and news.answers every two weeks.
-
- The information contained here is borrowed therefrom in large part.
-
- Gopher is a client/server protocol for building a distributed
- information delivery service. While providing a delivery vehicle for
- local information, Gopher also facilitates access to other Gopher and
- information servers on the Internet.
-
- Gopher servers and clients can be obtained via anonymous ftp to
- boombox.micro.umn.edu. Look in the directory /pub/gopher.
-
- There are clients for the following systems. For the latest
- directory information, see the FAQ.
-
- Unix Curses & Emacs
- Xwindows
- Macintosh Hypercard
- Macintosh Application
- DOS w/Clarkson Driver
- NeXTstep
- VM/CMS
- VMS
- MVS
-
- There are also a number of public telnet login sites available.
- See the FAQ for more information.
-
- There are servers for the following systems. For the latest
- directory information, see the FAQ.
-
- Unix
- VMS
- Macintosh
- VM/CMS
- MVS
-
-
- Papers and articles describing Gopher:
-
- _The_Internet_Gopher_, "ConneXions", July 1992, Interop.
-
- _Exploring_Internet_GopherSpace_ "The Internet Society News", v1n2 1992,
-
- _The_Internet_Gopher_Protocol_, Proceedings of the Twenty-Third
- IETF, CNRI, Section 5.3
-
- _Internet_Gopher_, Proceedings of Canadian Networking '92
-
- _The_Internet_Gopher_, INTERNET: Getting Started, SRI
- International, Section 10.5.5
-
- _Tools_help_Internet_users_discover_on-line_treasures, Computerworld,
- July 20, 1992
-
- Gopher will also be in two forthcoming O'Reilly Books:
- "Administrating TCP/IP, and The Whole Internet"
-
- ./ ADD NAME=FAQ
- From: gopher@boombox.micro.umn.edu (UofMN Gopher Team)
- Subject: Gopher (comp.infosystems.gopher) Frequently Asked Questions (FAQ)
- Summary: Common Questions and Answers about the Internet Gopher, a
- client/server protocol for making a world wide information
- service, with many implementations.
- Organization: University of Minnesota, Twin Cities
- Date: Thu, 23 Sep 1993 14:58:54 GMT
-
- Archive-name: gopher-faq
- Last-modified: 1993/08/16
-
- Common Questions and Answers about the Internet Gopher, a
- client/server protocol for making a world wide information service,
- with many implementations. Posted to comp.infosystems.gopher,
- comp.answers, and news.answers every two weeks.
-
- The most recent version of this FAQ can be gotten through gopher, or
- via anonymous ftp:
-
- rtfm.mit.edu:/pub/usenet/news.answers/gopher-faq
-
- Those without FTP access should send e-mail to mail-server@rtfm.mit.edu
- with "send usenet/news.answers/finding-sources" in the body to find out
- how to do FTP by e-mail.
-
- -------------------------------------------------------------------
- List of questions in the Gopher FAQ:
-
- Q0: What is Gopher?
- Q1: Where can I get Gopher software?
- Q2: What do I need to access Gopher?
- Q3: Where are there publicly available logins for Gopher?
- Q4: How can I add to the information in gopher?
- Q5: Who Develops Gopher Software?
- Q6: How can I set up a "CSO" phone book server? Where is the software?
- Q7: Why can't I access the University of Minnesota's UPI news?
- Q9: What are the type characters for the different Gopher Objects?
- Q10: When I do full-text searches I always get every document back, Why?
- Q11: When I try to build the UNIX software I get an error from make:
- "Must be a separator on rules line #. Stop" Why?
- Q12: What is the relationship between Gopher and (WAIS, WWW, ftp)?
- Q13: Are papers or articles describing Gopher available?
- Q14: On a DECstation I get the error message "/etc/svc.conf no such file
- or directory" when running the gopherd server, why?
- Q15: The boolean searching terms don't work for my full-text index, why?
- Q16: When linking the Unix gopher server with WAIS I get undefined symbols,
- Q18: Why don't my WAIS indexes work? I never get anything back for searches.
- or Why do I get "Dangling file" error messages in my logfile?
- Q19: My gopher server doesn't work under inetd, why?
- Q20: This is not a bug report, just a curiosity. I managed to install
- Q21: Help! I have PC-NFS and want to use the PC-Gopher client. How?
- Q22: How do I nuke a hung TCP connection? I can't restart my UNIX
- gopher server unless I get rid of it, and I don't want to reboot!
- Q23: Is there somewhere I can retrieve a list of announced gopher
- links? I'd like to keep a local, up-to-date list of available gopher
- holes without requiring our users to gopher to umn just to scan
- GopherSpace.
- Q24: Why doesn't my unix gopher client display ISO-Latin-1 characters
- Q25: What is veronica?
- Q26: What e-mail/usenet discussions lists are active for Gopher?
- Q27: How do I get my Gopher (whois/cso/library catalog) listed in gopher menus?
- Q28: Where is the registered list of gopher+ view types?
-
- -------------------------------------------------------------------
- Q0: What is Gopher?
-
- A0: The Internet Gopher client/server provides a distributed
- information delivery system around which a world/campus-wide
- information system (CWIS) can readily be constructed. While
- providing a delivery vehicle for local information, Gopher
- facilitates access to other Gopher and information servers
- throughout the world.
-
- -------------------------------------------------------------------
- Q1: Where can I get Gopher software?
-
- A1: via anonymous ftp to boombox.micro.umn.edu. Look in the directory
- /pub/gopher
-
- --------------------------------------------------------------------
- Q2: What do I need to access Gopher?
-
- A2: You will need a gopher "client" program that runs on your local PC
- or workstation
-
- There are clients for the following systems. The directory
- following the name is the location of the client on the anonymous
- ftp site boombox.micro.umn.edu (134.84.132.2) in the directory
- /pub/gopher.
-
- Unix Curses & Emacs : /pub/gopher/Unix/gopher+2.0.tar.Z
- Xwindows (athena) : /pub/gopher/Unix/xgopher.1.3.tar.Z
- Xwindows (Motif) : /pub/gopher/Unix/moog
- Xwindows (Xview) : /pub/gopher/Unix/xvgopher
- Macintosh Hypercard : /pub/gopher/Macintosh-TurboGopher/old-versions *
- Macintosh Application : /pub/gopher/Macintosh-TurboGopher/ *
- DOS w/Clarkson Driver : /pub/gopher/PC_client/
- NeXTstep : /pub/gopher/NeXT/
- VM/CMS : /pub/gopher/Rice_CMS/ or /pub/gopher/VieGOPHER/
- VMS : /pub/gopher/VMS/
- OS/2 2.0 : /pub/gopher/os2/
- MVS/XA : /pub/gopher/mvs/
-
- Many other clients and servers have been developed by others, the
- following is an attempt at a comprehensive list.
-
- A Microsoft Windows Winsock client "The Gopher Book"
- sunsite.unc.edu:/pub/micro/pc-stuff/ms-windows/winsock/apps/gophbook.zip
-
- A Macintosh Application, "MacGopher".
- ftp.cc.utah.edu:/pub/gopher/Macintosh *
-
- Another Macintosh application, "GopherApp".
- ftp.bio.indiana.edu:/util/gopher/gopherapp *
-
- A port of the UNIX curses client for DOS with PC/TCP
- oac.hsc.uth.tmc.edu:/public/dos/misc/dosgopher.exe
-
- A port of the UNIX curses client for PC-NFS
- bcm.tmc.edu:/nfs/gopher.exe
-
- A beta version of the PC Gopher client for Novell's LAN Workplace
- for DOS
- lennon.itn.med.umich.edu:/dos/gopher
-
- A VMS DECwindows client for use with Wollongong or UCX
- job.acs.ohio-state.edu:XGOPHER_CLIENT.SHARE
-
-
- * Note: these Macintosh clients require MacTCP.
-
- Most of the above clients can also be fetched via a gopher client
- itself. Put the following on a gopher server:
-
- Type=1
- Host=boombox.micro.umn.edu
- Port=70
- Path=
- Name=Gopher Software Distribution.
-
-
- Or point your gopher client at boombox.micro.umn.edu, port 70 and
- look in the gopher directory.
-
-
- There are also a number of public telnet login sites available.
- The University of Minnesota operates one on the machine
- "consultant.micro.umn.edu" (134.84.132.4) See Q3 for more
- information about this. It is recommended that you run the client
- software instead of logging into the public telnet login sites. A
- client uses the custom features of the local machine (mouse,
- scroll bars, etc.) A local client is also faster.
-
- ---------------------------------------------------------------------
- Q3: Where are there publicly available logins for Gopher?
-
- A3: Here is a short list, use the site closest to you to minimize
- network lag.
-
- Public Logins:
-
- Hostname IP# Login Area
- ------------------------- --------------- ------ -------------
- consultant.micro.umn.edu 134.84.132.4 gopher North America
- ux1.cso.uiuc.edu 128.174.5.59 gopher North America
- panda.uiowa.edu 128.255.40.201 panda North America
- gopher.msu.edu 35.8.2.61 gopher North America
- gopher.ebone.net 192.36.125.2 gopher Europe
- info.anu.edu.au 150.203.84.20 info Australia
- gopher.chalmers.se 129.16.221.40 gopher Sweden
- tolten.puc.cl 146.155.1.16 gopher South America
- ecnet.ec 157.100.45.2 gopher Ecuador
- gan.ncc.go.jp 160.190.10.1 gopher Japan
-
- It is recommended that you run the client software instead of
- logging into the public login sites. A client uses the
- custom features of the local machine (mouse, scroll bars, etc.)
- and gives faster response.
-
- ---------------------------------------------------------------------
- Q4: How can I add to the information in gopher?
-
- A4: You can do this by running a gopher server. Servers are available
- for a number of systems. Use anonymous ftp to
- boombox.micro.umn.edu (134.84.132.2) and look in /pub/gopher. The
- following servers are available there:
-
- Unix : /pub/gopher/Unix/gopher+2.0.tar.Z
- VMS : /pub/gopher/VMS/
- Macintosh : /pub/gopher/Mac_server/
- VM/CMS : /pub/gopher/Rice_CMS/ or /pub/gopher/Vienna_CMS/
- MVS : /pub/gopher/mvs/
- DOS PC : /pub/gopher/PC_server/
-
-
- When you have your server ready you can publish it to the world by
- sending e-mail to the maintainters of the "Other gophers" list.
- See Q27 for details.
-
- ---------------------------------------------------------------------
- Q5: Who Develops Gopher Software?
-
- A5: Gopher was originally developed in April 1991 by the University
- of Minnesota Microcomputer, Workstation, Networks Center to help
- our campus find answers to their computer questions.
-
- It has since grown into a full-fledged World Wide Information
- System used by a large number of sites in the world.
-
- Many people have contributed to the project, too numerous to
- count.
-
- The people behind the much of the gopher software can be reached
- via e-mail at gopher@boombox.micro.umn.edu, or via paper mail:
-
- Internet Gopher Developers
- 100 Union St. SE #190
- Minneapolis, MN 55455 USA
-
- Or via FAX at:
-
- +1 (612) 625-6817
-
- ---------------------------------------------------------------------
- Q6: How can I set up a "CSO" phone book server? Where is the software?
-
- A6: CSO phone book servers are also known as "qi" servers. The
- software implementation can be gotten via anonymous ftp from
- uxc.cso.uiuc.edu (128.174.5.50) as /pub/qi.tar.Z. You may also
- see this referred to as "ph", which is what most of the clients
- are called. A collected set of clients for Macs, PCs, VMS, VM,
- etc, are in the /pub/ph.tar.Z file.
-
- There is also an archive of the mailing list for qi/ph software on
- the same machine. It's in /pub/info-ph.archive. You may join the
- list by sending email to info-ph-request@uxc.cso.uiuc.edu.
-
- This software is supported by Paul Pomes <p-pomes@uiuc.edu>
- Contact him for more information.
-
- -------------------------------------------------------------------
- Q7: Why can't I access the University of Minnesota's UPI news?
-
- A7: The University of Minnesota has a site license for UPI news, we
- are not allowed to distribute it off of our campus. We get our
- UPI news from Clarinet. For more information about getting UPI
- news send mail to info@clarinet.com. For information about
- setting up your own gopher-UPI server search the gopher-news
- archive for UPI.
-
- -------------------------------------------------------------------
- Q9: What are the type characters for the different Gopher Objects?
-
- A9: Normal IDs.
-
- 0 Item is a file
- 1 Item is a directory
- 2 Item is a CSO (qi) phone-book server
- 3 Error
- 4 Item is a BinHexed Macintosh file.
- 5 Item is DOS binary archive of some sort.
- 6 Item is a UNIX uuencoded file.
- 7 Item is an Index-Search server.
- 8 Item points to a text-based telnet session.
- 9 Item is a binary file! Client must read until the connection
- closes. Beware.
- T TN3270 connection.
-
- Experimental IDs.
-
- s Sound type. Data stream is a mulaw sound.
- g GIF type.
- M MIME type. Item contains MIME data.
- h html type.
- I Image type.
- i "inline" text type (used by panda).
-
- -------------------------------------------------------------------
- Q10: When I do full-text searches I always get every document back, Why?
-
- A10: This is a problem occasionally encountered with Unix full-text
- indexes. It is caused by setting up the link incorrectly to a
- gindexd port.
-
- The Path= field should be *blank* when pointing to a gindexd
- index.
-
- Otherwise the client will send the path to the gindexd daemon,
- which interprets everything as a keyword. This path is
- likely to contain a pathname that is common to all of the indexed
- files. Thus a search generates hits on everything.
-
- Note that gindexd isn't used much anymore, this question does not
- apply if you are using the built in indexing in the Unix gopher
- server.
-
- -------------------------------------------------------------------
- Q11: When I try to build the UNIX software I get an error from make:
- "Must be a separator on rules line #. Stop" Why?
-
- A11: This is a problem with older makes that don't understand the "include"
- keyword. One easy way to cope with this problem is compiling GNU
- make, which does understand the include keyword.
-
- If this is too difficult, remove the line:
-
- include Makefile.config
-
- from all the Makefiles and paste in a copy of Makefile.config at
- the top of each Makefile.
-
- Or, instead of pasting you can make the client/server by going
- into the appropriate directory and typing:
-
- make -f ../Makefile.config -f Makefile
-
- -------------------------------------------------------------------
- Q12: What is the relationship between Gopher and (WAIS, WWW, ftp)?
-
- A12: Gopher is intimately intertwined with these other systems.
- As shipped the Unix gopher server has the capability to:
-
- - Search local WAIS indices.
- - Query remote WAIS servers and funnel the results to gopher
- clients.
- - Query remote ftp sites and funnel the results to gopher
- clients.
- - Be queried by WWW (World Wide Web) clients either using
- built in gopher querying or using native http querying.
-
- -------------------------------------------------------------------
- Q13: Are papers or articles describing Gopher available?
-
- A13: Gopher has a whole chapter devoted to it in :
-
- _The_Whole_Internet_users_guide_and_catalog by Ed Krol
- (publisher O'Reilley & Associates, Inc; ISBN: 1-56592-025-2).
- (Editors note: ...Great book, go out and buy a bunch!)
-
- _The_Internet_Passport: NorthWestNet's Guide to Our World Online"
- By Jonathan Kochmer and NorthWestNet. Published by NorthWestNet,
- Bellevue, WA. 1993. 516 pp. ISBN 0-9635281-0-6.
- Contact info: passport@nwnet.net, or (206) 562-3000
-
- _A_Students_Guide_to_UNIX by Harley Hahn. (publisher McGraw Hill,
- Inc.; 1993 ISBN 0-07-025511-3)
-
- _Intelligent_Information_Retrieval:_The_Case_of_Astronomy_and_
- _Related_Space_Sciences (A. Heck and F. Murtagh, editors). Published
- by Kluwer Academic Publishers, P.O. box 17, 3300 AA Dordrecht, the
- Netherlands. ISBN: 0-7923-2295-9
-
- Other references include:
-
- _The_Internet_Gopher_, "ConneXions", July 1992, Interop.
-
- _Exploring_Internet_GopherSpace_ "The Internet Society News", v1n2 1992,
-
- (You can subscribe to the Internet Society News by sending e-mail to
- isoc@nri.reston.va.us)
-
- _The_Internet_Gopher_Protocol_, Proceedings of the Twenty-Third
- IETF, CNRI, Section 5.3
-
- _Internet_Gopher_, Proceedings of Canadian Networking '92
-
- _The_Internet_Gopher_, INTERNET: Getting Started, SRI
- International, Section 10.5.5
-
- _Tools_help_Internet_users_discover_on-line_treasures, Computerworld,
- July 20, 1992
-
- _TCP/IP_Network_Administration_, O'Reilly.
-
- Balakrishan, B. (Oct 1992)
- "SPIGopher: Making SPIRES databases accessible through the
- Gopher protocol". SPIRES Fall '92 Workshop, Chapel Hill, North
- Carolina.
-
- Tomer, C. Information Technology Standards for Libraries,
- _Journal of the American Society for Information Science_,
- 43(8):566-570, Sept 1992.
-
-
- -------------------------------------------------------------------
- Q14: On a DECstation I get the error message "/etc/svc.conf no such file
- or directory" when running the gopherd server, why?
-
- A14: This is caused by the chroot() call in gopherd. It can be easily
- fixed by running gopherd with the -c option.
-
- Alternatively you can copy /etc/svc.conf into a directory named
- "etc" inside the gopher-data directory.
- -------------------------------------------------------------------
- Q15: The boolean searching terms don't work for my full-text index, why?
-
- A15: This is probably because the searching is being provided by WAIS.
- WAIS opts to return all documents that contain a search phrase
- within certain limits. WAIS searches do return the documents with
- the highest "score" at the top, those documents will have the
- closest relevance.
-
- Alternatively you could get a booleanized version of wais from
- ftp.bio.indiana.edu, or get the new freeWAIS.
-
- -------------------------------------------------------------------
- Q16: When linking the Unix gopher server with WAIS I get undefined
- symbols,
- such as:
-
- log_file_name
- logfile
- PrintStatus
- find_value
- Sources
- NumSources
-
- A17: This happens if you make gopherd before linking in the WAIS ir/ui
- directories. The fix is to "make clean" or remove
- gopherd/{waisgopher.o,Waisindex.o} and then remake gopherd. Or
- link the ir/ui directories first.
- -------------------------------------------------------------------
- Q18: Why don't my WAIS indexes work? I never get anything back for searches.
- or Why do I get "Dangling file" error messages in my logfile?
-
- A18: The problem could be in the server. The server should be run
- using the -c option if you want WAIS to work. Another solution is to
- patch the WAIS code so that it doesn't check the files on the disk.
- Search the gopher-news archive for "dangling". This will turn up a
- single document with the patch.
-
- -------------------------------------------------------------------
- Q19: My gopher server doesn't work under inetd, why?
-
- A19: It could be that your inetd server only supports a limited amount
- of arguments. For instance, the maximum number of arguments to an
- inetd server is 5. You can get around this by combining arguments: i.e.
-
- gopherd -I -c
-
- becomes:
-
- gopherd -Ic
-
- You may also leave the port specifier off of the command line.
- The gopher server automagically finds out the port it's running on.
-
- -------------------------------------------------------------------
- Q20: This is not a bug report, just a curiousity. I managed to install
- gopher on my PC, more or less by myself, which is a pretty good
- accomplishment, for someone who hasn't installed hardly anything on a
- PC. I then proceeded to load my PC/TCP kernel, ETHDRV, and try to
- start up gopher. It said it couldn't initialize that stack(?). I have
- to load this whenever I use PC/TCP. Incredibly, when I did not load
- ETHDRV, Gopher came up immediately and telneted to our local server.
- How does it know what kernel to load?
-
- A20 Dr. Science says,
-
- The Internet Gopher program is not actually computer program at
- all, but a collection of magical incantations handed down from Dark
- Age conjurors. It works by sending magical "demons" through the air,
- which scour the world for information, and then return to cast
- illusions containing the answer.
-
- When you use the Gopher, your computer isn't actually doing
- anything at all. Instead, these demons have mesmerized you with an
- evil magical spell, which was invoked by the pattern of
- finger-movements peculiar to the typing of the letters G-O-P-H-E-R on
- your keyboard. This spell transmits demonic information directly to
- your brain.
-
- Scientists aren't certain of the long-term effects of demonic
- mesmirization, although former presidents have suffered only minor
- medical side-effects from it. Indeed, since Magic and Science are
- usually opposed to each other, most Scientists are usually
- close-minded about such issues, and will usually respond with some
- vacuous non-answer about "packet drivers", "stacks", and other such
- jargon.
-
- Unlike conventional scientists, Dr. Science is very open-minded and
- is willing to deal with such issues in a frank and honest manner.
- This is why people come to him with questions, and why they've learned
- to rely on and live by his answers.
-
- Dr. Science
- "I'm not a real doctor; I have a Master's Degree.... in SCIENCE!"
-
- :-) :-) :-) :-)
- There's always room for a little humor in a FAQ..
- -------------------------------------------------------------------
- Q21: Help! I have PC-NFS and want to use the PC-Gopher client. How?
-
- A21: Use a piece of software called PKTMUX, available at fine ftp
- sites everywhere. This will let you use any packet driver
- application.
-
- Or, aquire a client that supports PC-NFS. See Q2.
- -------------------------------------------------------------------
- Q22: How do I nuke a hung TCP connection? I can't restart my UNIX
- gopher server unless I get rid of it, and I don't want to reboot!
-
- A22:
-
- Here is an example of using dbx to change a socket from CLOSING to
- CLOSED.
-
- # netstat -A|grep CLOSING
- c4bc5100 tcp 0 11 mymachine.gopher 129.89.8.4.70 CLOSING
- # dbx -k /vmunix /dev/mem
- ...
- (dbx) 0xc4bc5100+8/1X -- display contents of PCB+8
- c4bc5108: 00000007
- (dbx) assign 0xc4bc5108=0 -- zero it
- 0
- (dbx) q
-
- After a minute or two, the CLOSED socket should disappear.
- -------------------------------------------------------------------
- Q23: Is there somewhere I can retrieve a list of announced gopher
- links? I'd like to keep a local, up-to-date list of available gopher
- holes without requiring our users to gopher to umn just to scan
- GopherSpace.
-
- A23: In the Unix client/server distribution is a perl script called
- "gopherdist". Gopherdist can fetch the contents of any point in
- GopherSpace.
-
- To dump the contents of all the North American links from
- gopher.tc.umn.edu do the following:
-
- % gopherdist gopher.tc.umn.edu 70 "1/Other Gopher and Information
- Servers/North America" > .Links
- -------------------------------------------------------------------
- Q24: Why doesn't my unix gopher client display ISO-Latin-1 characters
- properly? BTW I'm using a Sun workstation..
-
- A24: It is the client's problem, the server is perfectly 8-bit transparent.
- The BSD curses library uses bit 8 in order to remember, whether a
- character has been displayed reverse. So use just /usr/5bin/cc and
- you get the System V curses version which is 8 bit clean.
-
- Note that this may be a problem under other versions of UNIX too...
-
- -------------------------------------------------------------------
- Q25: What is veronica?
-
- A25: veronica: Very Easy Rodent-Oriented Net-wide Index to
- Computerized Archives.
-
- veronica offers a keyword search of most gopher-server menu titles
- in the entire gopher web. As archie is to ftp archives, veronica
- is to gopherspace. A veronica search produces a menu of gopher
- items, each of which is a direct pointer to a gopher data source.
- Because veronica is accessed through a gopher client, it is easy
- to use, and gives access to all types of data supported by the
- gopher protocol.
-
- To try veronica, select it from the "Other Gophers" menu on
- Minnesota's gopher server, or point your gopher at:
-
- Name=veronica (search menu items in most of GopherSpace)
- Type=1
- Port=70
- Path=1/veronica
- Host=futique.scs.unr.edu
-
- ------------------------------------------------------------------
- Q26: What e-mail discussions lists are active for Gopher?
-
- A26: There are a couple of places where Gopher software and
- development is discussed.
-
- The USENET newsgroup comp.infosystems.gopher is the biggest
- discussion list.
-
- Gopher discussion also takes place on the mailing list
- gopher-news. To subscribe send a message to:
-
- gopher-news-request@boombox.micro.umn.edu
-
-
- A mailing list for VMS developers is also available, send e-mail
- to listserv@trln.lib.unc.edu with a message that contains
-
- sub VMSgopher-L firstname lastname
-
- A mailing list for MVS gopher developers and users is also
- available. To subscribe to the list, send mail to
- LISTSERVER@LISTS.ACS.OHIO-STATE.EDU containing:
-
- SUBSCRIBE MVSGOPHER firstname lastname
-
-
- ------------------------------------------------------------------
- Q27: How do I get my Gopher (whois/cso/library catalog) listed in gopher menus?
-
- A27: If your gopher server is in Europe, send mail to:
-
- gopher@ebone.net
-
- Otherwise send mail to:
-
- gopher@boombox.micro.umn.edu
-
- with the following information:
-
- The Server's Name (as it will appear on the menu)
- The Hostname
- The Port Number
- An Administrative contact
- A Selector String (optional)
-
-
- The list of CSO nameservers is maintained at Notre Dame by Joel Cooper.
- Any updates to the list should be sent to cooper@utopia.cc.nd.edu.
-
- The list of WHOIS servers is maintained at MIT by Matt Power. Any
- updates to the list should be sent to mhpower@athena.mit.edu.
-
- The Gopher to X.500 gateway is maintained at U. Michigan by Tim Howes.
- Any comments should be sent to tim@umich.edu.
-
- The list of Internet Accessible Libraries is is currently a
- collaborative effort between Marie-Christine Mahe at Yale
- University, Lou Rosenfeld at the University of Michigan, and
- Billy Barron at the University of Texas in Dallas. Barry Bouwsma
- steadily contributes many obscure foreign library listings.
-
- Error corrections and additions are always welcome, and should be
- sent to:
-
- GOPHLIB@GOPHER.YALE.EDU.
-
- ------------------------------------------------------------------
- Q28: Where is the registered list of gopher+ view types?
-
- A28: It's available via anonymous ftp from
-
- isi.edu
-
- in the directory
-
- /in-notes/mime
-
-
- --
- | Paul Lindner | lindner@boombox.micro.umn.edu | Slipping into madness
- | | Computer & Information Services | is good for the sake
- | Gophermaster | University of Minnesota | of comparison.
- ///// / / / /////// / / / / / / / / //// / / / / / / / /
-
-
- ./ ADD NAME=MVSFAQ
- MVS Gopher Frequently Asked Questions List
-
- January 16, 1994
-
- This list addresses common questions and problems about the MVS
- Gopher client and server. I hope to update this list and repost
- it to MVSGOPHER on a regular basis, time permitting.
-
- Note that some items describe restrictions or misfeatures that
- clearly ought to be rectified. Rest assured that there is a
- "wish list" and these will be included in future releases, but
- only as time permits.
-
- Thanks to those too numerous to name individually for helping me
- to come up with answers to problems with the installation of MVS
- Gopher on various systems.
-
- Please feel free to submit additional questions (and answers) to me
- for inclusion or correction.
-
- - Steve Bacher (Batchman) <seb@draper.com>
- - Draper Laboratory
-
- ----------------------------------------------------------------------
-
- Summary of Changes:
-
- 04 Aug 1993 - added question Q-0
- updated email addresses
- public distribution clarified
- 04 Aug 1993 - FAL changed to HAL
- 10 Aug 1993 - V2R2 is on boombox now
- Added note about MTF and C/370 V1
- 13 Aug 1993 - Another FTP site
- More info about the MVSGOPHER list itself
- 17 Aug 1993 - Answer to KILL -38 question
- Removed specific reference to VM LISTSERV
- 31 Dec 1993 - Updated for V3
- 16 Jan 1994 - new email address for Shawn Hart; no longer prerelease
-
- ----------------------------------------------------------------------
-
- Summary of Questions:
-
- Q-0: Why the MVSGOPHER mailing list?
- Q-1: What is Gopher?
- Q-2: Where can I get the MVS Gopher?
- Q-3: How do I get software from SERVICE@USCMVSA?
- Q-4. What do I need to run the MVS Gopher?
- Q-5. Do I need XPROC? Where can I get it?
- Q-6. Who wrote the MVS Gopher?
- Q-7. Do I have to pay for MVS Gopher? Who owns it?
- Q-8. Can I use REXX in MVS Gopher?
- Q-9. What is this multitasking problem?
- Q-10. Won't Gopher chew up a lot of CPU resources?
- Q-11. What do I have to do to TCP/IP to use the Gopher client?
- Q-12. What do I have to do to TCP/IP to use the Gopher server?
- Q-13. How do I connect to a different server from the MVS client?
- Q-14. Why can't I run more than one MVS TCP/IP client from TSO?
- Q-15. Where can I get XTELNET?
- Q-16. How do I specify that the MVS Gopher client should use XTELNET?
- Q-17. I get PANEL NOT FOUND errors after using the MVS Gopher.
- Q-18. I get garbage on my screen when Gopher can't open my EXTRACT file.
- Q-19. When I try to run the MVS Gopher Server, I get gethostname errors.
- Q-20. I can't access the "About This Gopher" item of the MVS server.
- Q-21. How do I stop the server?
- Q-22. I can't compile Gopher because...
- Q-23. I can't linkedit Gopher because...
- Q-24. I can't run the Gopher server because...
- Q-25. I can't run the Gopher client because...
- Q-26. I can't run the Gopher server or client because...
- Q-27. I get an 0C1 ABEND when I try to run the server/client
- Q-28. I can't figure out how to define the main Gopher menu to the server.
- Q-29. Why doesn't the Gopher client honor my additional parameters,
- Q-30. Why can't I attention out of the Gopher client?
- Q-31. Why do I have to "S" (select) an item before I can "E" (extract) it?
- Q-32. Where's the tutorial?
- Q-33. What's the deal with the "w" type?
- Q-34. How can I debug a Gopher server REXX exec?
- Q-35. What hostname and port hacks?
- Q-36. What MVS file types does the Gopher server support?
- Q-37: How can I display square brackets while viewing text?
- Q-38: How can I make the client start up at a specific bookmark file?
- Q-39: Can I set up client items that do anything my users would want?
-
- ----------------------------------------------------------------------
-
- Q-0: Why the MVSGOPHER mailing list?
-
- A. It's much harder to get a USENET newsgroup started than a private
- mailing list. The procedure for creating a new newsgroup is
- considerably more formal and involves lots of voting.
-
- It's true that we could use comp.infosystems.gopher or IBMTCP-L, but
- both of those have plenty of traffic as it is, and there are issues
- pertaining to MVS Gopher that would bore the other readers.
-
- It is possible to gateway mailing lists to newsgroups locally.
-
- List servers offer the following options that the user can control
- via email. One may choose to have mail delivered...
- (1) as usual - that is, as mail is sent to the list it is resent
- to you; this seems to be what you object to
- (2) you may receive a digest - daily, weekly, monthly, your choice -
- where all mail distributed is sent to you as a package
- (3) opt NOT to receive email and instead persuse the distributed mail
- at your convenience using special commands sent to the server
- by email; you can opt to read only new mail (since a certain date),
- only mail about certain topics, from certain people, whatever you
- choose;
-
- Should a newsgroup be set up, a list server will also allow all email
- sent to it to automatically be posted to the newsgroup.
-
- So, if you're not already on the list, you can join by sending a
- message with "SUBSCRIBE MVSGOPHER yourfirstname yourlastname" to
- LISTSERVER@LISTS.ACS.OHIO-STATE.EDU.
-
- ----------------------------------------------------------------------
-
- Q-1: What is Gopher?
-
- A. Gopher is a distributed information delivery service. That sounds
- quite boring, which is why people prefer the name "gopher". The
- original Gopher came out of the University of Minnesota and ran
- on Unix machines. Subsequently it has been ported to virtually
- every known architecture, both clients and servers. Thus, a Gopher
- client on MVS can access data being served by any other kind of
- machine, and a Gopher server on MVS can allow clients on any
- platform to read mainframe data.
-
- If you really want to know all about Gopher, read the Gopher FAQ
- posting on the comp.infosystems.gopher newsgroup. This FAQ, and
- the mailing list that owns it, are for Gopher on MVS only.
-
- ----------------------------------------------------------------------
-
- Q-2: Where can I get the MVS Gopher?
-
- A. The MVS Gopher client and server is available via anonymous FTP from:
-
- boombox.micro.umn.edu /pub/gopher/mvs
- ftp.mic.ucla.edu /pub/mvs/gopher
- info2.rus.uni-stuttgart.de /pub/comm/infosystems/gopher/mvs
-
- Latest MVS Gopher on boombox.micro.umn.edu: Version 2 Release 2
- Latest MVS Gopher on ftp.mic.ucla.edu: Version 3 Release 1
- Latest MVS Gopher on info2.rus.uni-stuttgart.de: Version 2 Release 2
-
- Although the entire Gopher package is included in the single giant
- JCL stream that the distribution consists of, you don't have to
- install it all. You can install just the server or just the client
- if that's all you're interested in. The README file for the latest
- version/release explains how to FTP the distributions.
-
- You also have the choice of getting either the C language source or the
- precompiled object code. Also, the UCLA site has more up-to-date
- releases, including beta releases. The boombox version is frequently a
- release or two behind, since it is intended to be the "reliable" version.
-
- ----------------------------------------------------------------------
-
- Q-3: How do I get software from SERVICE@USCMVSA?
-
- A. You can't. This service was discontinued on August 31, 1993.
- Use the FTP site at ftp.mic.ucla.edu instead. For more information,
- contact Leonard Woren <ldw@usc.edu>.
-
- ----------------------------------------------------------------------
-
- Q-4. What do I need to run the MVS Gopher?
-
- A. C/370 Version 2 (SAS/C support is not currently available but
- is under development)
-
- Note: C/370 Version 1 may be OK for the client, but the server
- definitely needs C370 version 2.
-
- IBM TCP/IP or Interlink SNS/TCPaccess
-
- ISPF V2R2 or higher. V3 for best results, otherwise you
- may be forced to do a lot of hand-hacking of the panels.
-
- TSO/E V2 or higher to use the REXX interface. Some of the new
- capabilities in the MVS Gopher V3 REXX interface require REXX 3.46,
- which is available with TSO/E V2.3.1.
-
- If you don't have any C compiler, you can get the object code
- distribution (see answer to above question). However, in that
- case, you must have the IBM C/370 runtime library installed,
- since the object code was compiled with C/370 Version 2.
- Also, you must be running IBM TCP/IP (HAL) V2 and ISPF V3.
-
- ----------------------------------------------------------------------
-
- Q-5. Do I need XPROC? Where can I get it?
-
- A. Until recently, you needed XPROC if you wanted to be able to
- pass parameters to the GOPHER client TSO command (REXX exec).
- Now, there is some REXX parsing code that can simulate the
- TSO parameter extraction. But you're still better off using
- XPROC if you want truly robust parsing.
-
- XPROC is available from ftp.mic.ucla.edu (the same as one of
- the Gopher source sites, if you're sharp-eyed), in directory
- /pub/mvs/util. It's in the TSOREXX distribution, which also
- includes the XWRITENR utility (which emulates TSO CLIST
- WRITENR for REXX execs).
-
- ----------------------------------------------------------------------
-
- Q-6. Who wrote the MVS Gopher?
-
- A. The MVS Gopher Server was originally by Shawn Hart at the
- University of Delaware. Subsequently, Steve Bacher made
- enhancements to it, and also wrote the client. Shawn Hart
- is currently at shart@indial1.io.com.
-
- Various enhancements and customizations to both the client and
- the server have been contributed by:
-
- Lou Joseph <cwmy5c@irishmvs.cc.nd.edu>
- Denis DeLaRoca <csp1dwd@mvs.oac.ucla.edu>
- Dwight Cook <sysdc@uokmvsa.backbone.uoknor.edu>
- Rachna Agrawal <rachna@clemson.clemson.edu>
-
- ----------------------------------------------------------------------
-
- Q-7. Do I have to pay for MVS Gopher? Who owns it?
-
- A. MVS Gopher is distributed publicly for free, but is not in
- the public domain.
-
- Here is the standard disclaimer:
-
- Copyright (c) The Charles Stark Draper Laboratory, Inc.,1992,1993,1994
-
- MVS Gopher Server originally by Shawn Hart (Univ. of Delaware).
-
- This software is provided on an "AS IS" basis. All warranties,
- including the implied warranties of merchantability and fitness,
- are expressly denied.
-
- Provided this copyright notice is included, this software may
- be freely distributed and not offered for sale.
-
- Changes or modifications may be made and used only by the maker
- of same, and not further distributed. Such modifications should
- be mailed to the author for consideration for addition to the
- software and incorporation in subsequent releases.
-
- ----------------------------------------------------------------------
-
- Q-8. Can I use REXX in MVS Gopher?
-
- A. The server has a REXX interface: you can define menu items
- which fire up REXX execs in the server's address space.
- However, beware of the multitasking problem.
-
- MVS Gopher V3 has a completely reworked interface which
- solves the "multitasking problem" by allowing REXX execs
- to run outside of a TSO environment. However, TSO/E 2.3.1
- is required for this (see Q-4).
-
- Also, the client is driven by a REXX exec as a TSO command.
-
- ----------------------------------------------------------------------
-
- Q-9. What is this multitasking problem?
-
- A. Due to TSO/E architectural limitations, a Gopher server that runs
- REXX execs in a TSO environment must be single-threading. However,
- you can run more than one Gopher server at a time, so this is not a
- show-stopper. You can run a multithreading Gopher server that
- services only files, and a singlethreading Gopher server that
- services files and REXX exec services. You simply set up different
- GGPARMS files - one says "MTFTASKS 1" and the other says "MTFTASKS 8"
- or whatever number you want. They must also have differing port
- numbers (e.g. one at port 70 and one at port 1570).
-
- MVS APAR OY20253 addresses multitasking problems with TSO services.
- For TSO/Extensions V2R3, just to take one instance, PTFs UY35936 and
- UY35937 address these, but have a long PE chain against them.
- Upgrading TSO/E from V2R3 to V2R4 might help resolve these, but
- you're still stuck with the basic design of TSO, which is definitely
- not friendly to concurrency. Take ddnames (please). Dynamic
- allocation that uses preset ddnames is clearly not going to work
- well in a concurrent TSO environment.
-
- The most obvious difficulty used to be that the Gopher-REXX
- interface requires that REXX execs write to SYSTSPRT. Clearly more
- than one can't do this at the same time. This has changed in MVS
- Gopher V3, which has a completely new REXX interface. This solves
- the "multitasking problem" by allowing REXX execs to run without a
- TSO environment. Note that TSO/E 2.3.1 is required for this (see
- Q-4). Also, if you want to write REXX execs that use TSO services
- or call programs that require specific ddnames, you are still stuck
- with the need to run them under a single-threading Gopher server.
-
- ----------------------------------------------------------------------
-
- Q-10. Won't Gopher chew up a lot of CPU resources?
-
- A. The client won't, because it's just an ISPF dialog program
- that makes a lot of short, brief network connections. If you're
- still running V1, though, you will use up a lot of CPU in the ISPF
- browse interface, which was totally rewritten in V2.
-
- The server does somewhat more work, but (unlike the CMS gopher
- server, which is written in REXX), it's written in C, so it's
- reasonably fast. However, if you write REXX execs to serve some
- Gopher items, they will obviously chew up CPU resources, depending
- on what they do.
-
- If you want to get an idea of usage, start with the gopher server
- log, which you can see as part of the regular output of the gopher
- server (e.g. via SDSF). Also, if you have enabled them, you can use
- the write-to-programmer messages issued by the Gopher server, which
- are compatible with the UMn-format messages (I don't believe that
- the look and feel of these messages has been patented yet).
-
- ----------------------------------------------------------------------
-
- Q-11. What do I have to do to TCP/IP to use the Gopher client?
-
- A. No special action is required for the client. However, if
- your users are likely to run more than one TCP/IP client
- socket application from the same TSO session, then make sure
- that you have the "IUCVMULT" PTF for IBM's HAL. See Q-14.
-
- ----------------------------------------------------------------------
-
- Q-12. What do I have to do to TCP/IP to use the Gopher server?
-
- A. For IBM (HAL) TCP/IP...
-
- The following is from the installation instructions for the server:
-
- Add the name of the Gopher server started task (the name as it
- appears in SYS1.PROCLIB, not necessarily "GOPHER") to the MVS TCPIP
- profile data set (or have your MVS TCP/IP system programmer do it).
- In the examples below, let's say you've called it GOPHSRV. Add this
- in 2 places:
-
- (a) under AUTOLOG, so that TCP/IP will start the Gopher server
- automatically (a la inetd for unix) when a client connects.
- Just add the name to the list (e.g. GOPHSRV).
-
- (b) under PORT, so nobody can spoof the Gopher port. The format
- here is: 70 TCP GOPHSRV
-
- Repeat both for whatever number of Gopher server started tasks you
- create (with different port numbers).
-
- For Interlink SNS/TCP...
-
- By permission of the author:
-
- posted to IBMTCP-L on 27 May 1993 by Lou Joseph
- <CWMY5C%IRISHMVS.CC.ND.EDU@uicvm.uic.edu>
-
- I have looked further and found another place where
- the hostname is given. I think that this one is more likely to be used
- by gethostname(). It is in member DNRALCnn in SNSTCP.V110.PARM. Here is
- a copy of our DNRALC01:
-
- ACSS IRISHMVS.CC.ND.EDU. OUR SNS/TCP SUBSYSTEM NAME
- LOOPBACK 127.0.0.1 SNS/TCP LOCAL HOST NAME
- LOCALHOST 127.0.0.1 SNS/TCP LOCAL HOST NAME
-
- ACSS is the SNS/TCPaccess Subsystem Name. Note that there is a period
- after the EDU in the first line.
-
- Lou
-
- Lou Joseph CWMY5C@IRISHMVS.BITNET
- Office of University Computing Louis.Joseph.2@ND.EDU
- University of Notre Dame
- Room G005 CCMB
- Notre Dame, IN 46556 (219) 631-7055
-
- ----------------------------------------------------------------------
-
- Q-13. How do I connect to a different server from the MVS client?
-
- A. Use the syntax GOPHER SERVER(other.server.host). You should have
- XPROC available for your GOPHER command to parse this in the most
- reliable fashion (see Q-5).
-
- You can also connect to another server by modifying your GOPHERRC
- data set (or specifying an alternate one with the INITFILE keyword,
- new in Gopher V3). Your default GOPHERRC file will have a section
- in it that looks something like this:
-
- Initial:
-
- Type=DIRECTORY
- Name=Primary (Root) Gopher Menu
- Path=
- Host=mvs.draper.com
- Port=70
- End
-
- Just remove that section (or comment it out by sticking "#" characters
- in front of the lines) and Gopher will prompt you for a server name.
- Or else you can replace the value of the Host= line with the server
- you want to connect to. For example, change
-
- Host=mvs.draper.com
-
- to
-
- Host=testhost.elsewhere.com
-
- ----------------------------------------------------------------------
-
- Q-14. Why can't I run more than one MVS TCP/IP client from TSO?
-
- A. (sigh) Do you really want to know?
-
- IBM TCP/IP for MVS has had difficulties in managing more than one
- active client application per MVS/TSO address space.
-
- There were several parts to this problem:
-
- (1) Applications that use C language sockets cannot coexist with
- each other
-
- (2) Applications that use C language sockets cannot coexist with
- applications that use the Pascal-based interface
-
- (3) Applications that use the Pascal-based interface cannot
- coexist with each other
-
- As a consequence of (2) and (3), if an application using the
- Pascal-based interface is active, no other client application,
- either Pascal-based or socket-based, can be active in the same
- MVS address space.
-
- In TCP/IP for MVS Version 2 Release 1,
- IBM has partially solved (1), but has not solved (2) or (3).
-
- The solution involved creating a new module called IUCVMULT which would
- be loaded into the environment to track IUCV identifications within an
- address space. IUCVMULT is a serially reusable module, so that there
- is one shared copy per address space. Since IUCVMULT is loaded by the
- first call to a C socket routine, the first C socket application in the
- address space must hang around, which is potentially disastrous.
-
- This solution has several weaknesses:
-
- * The aforementioned requirement that IUCVMULT must be loaded
- in such a way as to allow all clients to see the same copy.
-
- * It does not address the problem of non-socket applications.
-
- * The requirement for the first socket application to remain
- active as long as the user needs to run any socket clients
- carries the potential for disaster. It means that a user
- cannot start application X, then start application Y, then
- terminate application X without crashing application Y.
- It also requires the user to remember which application
- was brought in "first", when in the ideal world the user
- should not even have to know if a given application is a
- TCP/IP client or not.
-
- * In a multiple-job-step-TCB environment (e.g. IMS), or a
- multi-session vendor product like TSC's PIE MultiTSO, which
- creates multiple job step TCB's with separate job pack areas,
- it is possible to have TCP/IP socket applications under
- different sessions at the same time with distinct copies
- of IUCVMULT. This produces disastrous results, as it
- has been known to cause the TCP/IP address space to crash.
-
- IBM shipped PTF UN13465 for APAR PL83602. Results showed that we were
- able to run our C socket application, fire up FTP while it was active,
- and not crash the socket application. However, firing up a second FTP
- in this environment caused an ABEND.
-
- One way to get around this, once you have the IUCVMULT fix, is
- to use Denis DeLaRoca's XTELNET instead of TELNET.
-
- ----------------------------------------------------------------------
-
- Q-15. Where can I get XTELNET?
-
- A. From ftp.mic.ucla.edu, directory /pub/mvs/xtelnet.
-
- ----------------------------------------------------------------------
-
- Q-16. How do I specify that the MVS Gopher client should use XTELNET?
-
- A. If you have V2R2, you can put the following line in your
- GOPHERRC file:
-
- Telnet: XTELNET
-
- If you want to make this change for everyone, then you must install
- the Gopher client in such a way as to insure that all GOPHERRC
- files are built in the correct way. There is code in the GOPHER
- exec that sets the value of the TELNET command, as well as a few
- other things. Use that to establish XTELNET as a default.
-
- ----------------------------------------------------------------------
-
- Q-17. I get PANEL NOT FOUND errors after using the MVS Gopher.
-
- A. You're using ISPF LIBDEF. LIBDEF is broken because it blows away
- previously set LIBDEFs. LIBDEF should be used only for testing
- ISPF applications, not production. Copy the ISPF panels and
- the GGCLIENT load module into production libraries - i.e. the
- ones all TSO users get at logon time - and ditch LIBDEF. For
- more information, try contacting the SHARE ISPF project to hear
- their whole sad story.
-
- ----------------------------------------------------------------------
-
- Q-18. I get garbage on my screen when Gopher can't open my EXTRACT file.
-
- A: The problem is that CBIPO, at least up through 92A, ships a
- broken C/370 runtime -- they installed all the FMIDs, so you get
- execution error messages in Kanji. perror() calls to stderr are
- what are affected.
-
- In other words, you have FMID JCLB212 installed instead of JDL1214,
- JCLB212 is the Kanji messages feature. JDL1214 is the messages for
- the Common Library. For C without PL/1, apparently you weren't
- supposed to install a separate FMID for messages at all.
-
- Solution 1: Install JDL1214 and hope it clobbers the other one!
- (But it won't.)
- Solution 2: Uninstall JCLB212.
- Solution 3: Order C/370 from IBM and start over from scratch.
-
- Neither of the above has been tried by anyone, to my knowledge.
-
- Also see Q-22.
-
- ----------------------------------------------------------------------
-
- Q-19. When I try to run the MVS Gopher Server, I get gethostname errors.
-
- A. Thanks to Mike Porter at the University of Delaware for this reply,
- posted to IBMTCP-L on 27 May 1993.
-
- One problem we've been seeing with 'gopher' and 'gethostname'
- really has nothing to do with either. Its just that this is
- the most common socket application our users run. (finger
- doesn't work either - for instance, nor will any socket call.)
-
- I spent some time tracking down the problem, but got lost in the
- platform support code. What seems to happen is a control block
- that is created once per session gets left around when an address
- space terminates. All future attempts to do an IUCV_set will fail
- until an IPL occurs.
-
- This is sort of like the old 'can't run two tcp/ip applications
- from the same address space', but not exactly. The old problem
- would clear up when the user would log off, but in this case,
- apparently MVS needs to be ipled. Perhaps the resource manager is
- not cleaning up like it should?
-
- One way to see if this is the problem is to run MVPXDISP (its in
- SEZALINK, and needs to be authorized, so add it to the auth. cmd
- list and update the tso parms. And no, it won't run in batch).
-
- This is the output received for a user that can't run gopher:
-
- MVPMVP656I MVPXDISP: VMCF: Pending count=1 Flags=40000000.
- MVPMVP655I MVPXDISP: IUCV: Connections=1, Max=255.
- MVPMVP662I MVPXDISP: IUCV: Ctl flags=00000000 Appl flags=00000000.
- MVPMVP650I MVPXDISP: User MIS0175 Asid 00A5. *****
- MVPMVP651I MVPXDISP: Data @ 0302A5C0 Sm=00 Cr0=000000E3 Flags=38.
- MVPMVP652I MVPXDISP: Client of the VMCF address space.
- MVPMVP652I MVPXDISP: Client of IUCV.
- MVPMVP653I MVPXDISP: IUCV mask=F8F8, Pending Ctl=0000, Appl=0820.
- MVPMVP654I MVPXDISP: VMCF: Buf=002E9030, Len=00000118, Flgs=00 User=
- Key=80.
-
- A talk with level 1 yields a solution of 'use another userid' or
- 'ipl' (stopping and restarting the tcpip address space doesn't
- help since the data appears to be associated with the subsystem).
-
- A: Here's something for SNS/TCP users with gethostname problems:
-
- From: Lou Joseph <CWMY5C%IRISHMVS.CC.ND.EDU@uicvm.uic.edu>
- Subject: Re: gethostname under MVS
-
- There is a configuration member in SNSTCP.V110.SAMP named ACPCONFG. It
- has to be customized, assembled and linked into SNSTCP.V110.LOAD.
- There is a MACRO ACFHOST in ACFCONFG with keywords MEMBER and DOMAIN.
- We have MEMBER=IRISHMVS and DOMAIN=CC.ND.EDU.
-
- That's the only place I could find where the local host name is set.
-
- Lou
-
- ---
-
- (In the old days I used to require that you stick the host name into
- the source code somewhere, but that kind of went away when I realized
- that gethostname() would do it. So I don't remember where or how I
- would insert the host name now. - seb)
-
- ----------------------------------------------------------------------
-
- Q-20. I can't access the "About This Gopher" item of the MVS server.
-
- A. This is because of a limitation that has been fixed in V2R3 of
- MVS Gopher. In the distributed installation instructions, it
- suggets that the "About This Gopher" PDS is to be referenced in
- the menu as PATH=DD:GGABOUT(ABOUT). This is what's in the
- sample server JCL.
-
- However, if you do this, then the subentries of this menu
- won't work, because they use the PATH=(MEMBER) feature, which
- didn't work when the current PDS was specified using the DD:
- format. V2R3 allows this. But in the meantime, read the
- note in the installation instructions that says to change
- the menu entry from PATH=DD:GGABOUT(ABOUT) to
- PATH=DATA.SET.NAME(ABOUT), where DATA.SET.NAME is the name
- of your "ABOUT" PDS.
-
- ----------------------------------------------------------------------
-
- Q-21. How do I stop the server?
-
- The MVS Gopher server, being a plain C program, doesn't understand
- operator "STOP" commands. Just use the operator "CANCEL" command
- from the console. For example, if you installed it as GOPHSRV in
- 'SYS1.PROCLIB' you would start it via:
-
- START GOPHSRV or S GOPHSRV
-
- and you would stop it by
-
- CANCEL GOPHSRV or C GOPHSRV
-
- It'll come down with a system 222 ABEND, which looks ugly, but is
- really quite harmless.
-
- ----------------------------------------------------------------------
-
- Q-22. I can't compile Gopher because...
-
- Q. It says it can't find the header file "time.h".
-
- A: Leonard Woren had this problem with C/370 1.1 and then again with
- V2. The problem is that C/370 is shipped with TIME as a MAC, which
- collides with the MVS TIME macro when C/370 is installed in the same
- zone as MVS. The CBIPO build ignores the error message about this,
- and ships a non-usable C/370. There's a PTF which adds EDCMTIME
- with an MALIAS of TIME to fix this problem. The PTF for HCCM202 is
- UN12293. Note that spc.h has the same problem, which is fixed by
- UN17425 (EDCMSPC). Also note that CBIPO, at least up through 92A,
- ships a broken C/370 runtime -- they installed all the FMIDs, so you
- get execution error messages in Kanji. See Q-18.
-
- ----------------------------------------------------------------------
-
- Q-23. I can't linkedit Gopher because...
-
- Q. I get TABLE OVERFLOW ... TOO MANY EXTERNAL SYMBOLS IN ESD
-
- A. The SYSLIB should point to 'TCPIP.COMMTXT' or 'TCPIP.SEZACMTX'
- depending on the level of TCP/IP. If you're pointing it at
- 'TCPIP.COMMMAC' or 'TCPIP.SEZACMAC', then of course your link
- is going to lose big.
-
- Q. it says that ATEXIT is multiply defined
-
- A. Under certain circumstances, people get a linkage editor warning
- when they build Gopher, saying that ATEXIT is multiply defined. It
- is because the C/370 MTF (multitasking) library has a different
- atexit() from the normal C library. Make sure that the linkedit of
- load module GGSTASK has the INCLUDE SYSLIB(EDCMTFS) control
- statement, and that the linkedit of load module GGSERVER (or
- GGSERVE, in Gopher V3) does *not* have an INCLUDE SYSLIB(EDCMTFS)
- control statement.
-
- Q. it can't find FCNTL or MTF or mtf.h
-
- A. You can't use C/370 V1 with the server. Get C/370 V2 or stick
- with the client only. If you stick with the client and your
- problem is that include file mtf.h is not found, then you'll
- have to remove that line from header file GG before continuing.
-
- ----------------------------------------------------------------------
-
- Q-24. I can't run the Gopher server because...
-
- Q. it gets an 0Cx abend
-
- A. Did you just install TCP/IP 2.2.1 and forget to relink your Gopher
- with the 2.2.1 TCP/IP routines?
-
- Q. it gets "The GIVESOCKET timed out"
-
- A. Not sure, but this went away for some users when they
- upgraded their TCP/IP...
-
- Q. I get: TCPIP severed IUCV path. Reason 'KILL -38 '
-
- A. Chuck Sechler <TS0258@ohstmvsa.acs.ohio-state.edu> says:
- We get this every time we shut down the system. When we shut down,
- we do not CANCEL GOPHER, but we stop TCPIP. I always assumed that
- this severed a connection with GOPHER, which led to the KILL -38
- message. This also leads to an ABEND for GOPHER of A03, which seems
- plausible.
-
- Q. the subtasks get weird abends
-
- A. Make sure that you're not running REXX exec requests from a
- server that runs under s TSO environment and is multithreading
- (MTFTASKS > 1). See Q-8.
-
- Q. I get EINVAL errors on GIVESOCKET and/or ABENDA03
-
- A. Perhaps you are running SIMTCPIP from SIMWARE, which relinks
- the entire Gopher module? In effect, this is running TCPIP 2.1
- with a Gopher that has TCPIP 2.2 stuff linked in.
-
- Q. I get gethostname() failures
-
- A. See Q-19. If that doesn't apply, make sure you've got the
- latest MVS Gopher, because I've fixed a lot of bugs in this.
- One user had been linking their Gopher with the wrong copy of
- CMMVSYS, which defines the IBM TCP/IP address space name!
-
- Q. I'm getting 001 ABENDS on the SYSTSPRT file.
-
- A. You need to debug your REXX execs (see Q-34). You could be
- allocating not enough space in your server JCL to hold a lot
- of output, or there could be trash being spewed out by your
- REXX exec.
-
- Actually, this whole problem will go away if you get MVS Gopher V3,
- which has a whole new REXX interface. But you'll have to stop
- writing to SYSTSPRT.
-
- Q. I get "Unknown host MVS.DRAPER.COM"
-
- A. You need to configure the server. You can do this by specifying
- "DOMAIN my.actual.site" in the GGPARMS startup file in the server.
- If you have the source code distribution, you can also accomplish
- this by changing the value of the MY_DOMAIN_SUFFIX preprocessor
- variable in the GGUSER header file.
-
- ----------------------------------------------------------------------
-
- Q-25. I can't run the Gopher client because...
-
- Q. I get "The parallel load module was not found. Could not set up
- the TCP environment."
-
- A. You need C/370 V2 and you must make sure that you linkedit the
- server with the "INCLUDE SYSLIB(EDCMTFS)" line.
-
- Q. I get "Unknown host MVS.DRAPER.COM"
-
- A. You need to configure the client. You can do this by modifying
- the GOPHERRC file (or modifying the code in the GOPHER exec that
- creates the GOPHERRC file for new users), or, if you have the
- source code distribution, by changing the value of the
- MY_DOMAIN_SUFFIX preprocessor variable in the GGUSER header file.
-
- Q. I get "Unknown host FOO.MYDOMAIN.NAME"
-
- A. You need to talk to whoever maintains your MVS TCP/IP site and
- ask about host tables and domain name servers. Tell them that
- MVS socket applications are not recognizing hostnames with the
- local domain name included when they do gethostname() calls,
- and gethostbyname() is not working when the domain name is
- included. If that doesn't help, try changing the value of the
- APPEND_DOMAIN_NAME_TO_SELF preprocessor variable in the GGUSER
- header file - but this may cause other servers to become
- impossible to reach.
-
- ----------------------------------------------------------------------
-
- Q-26. I can't run the Gopher server or client because...
-
- Q. It won't let me see files that I'm sure I've put in the
- ACCESS file. Or other random garbage. Or not seeing CR/LF's.
-
- A. There could be a problem with ASCII-EBCDIC translation.
- Or you could be communicating with a VM/CMS Gopher that has problems
- talking to MVS because of problems with the ASCII/EBCDIC translation
- at their end. For example, CMS Gopher prior to version 2.4. If so,
- make sure that the site in question gets a new CMS gopher from
- troth@ricevm1.rice.edu.
-
- If you want to tweak your own translation, ask Doron Shikmoni
- <P85025@BARILVM.BITNET> about usermods to the TCP/IP translate tables.
-
- Also keep in mind that with MVS Gopher V3, you must stop and
- restart your Gopher server whenever you make a change to the
- access file. And, since the access file is processed quite
- differently from the way it was in V2, you should reread the
- description of the access rule processing and make sure that
- you understand what it is doing.
-
- ----------------------------------------------------------------------
-
- Q-27. I get an 0C1 ABEND when I try to run the server/client
- right after I linkedited it.
-
- A. Possibilities:
-
- Could be you don't have the C runtime library present in the system
- link list or STEPLIB. This could apply to C/370 or SAS/C. For the
- client, you can do this via ISPLLIB or LIBDEF (but see Q-17). For
- the server, you can use STEPLIB. But the best answer is to pester
- your MVS systems programmer to put the C runtimes in linklist.
-
- ----------------------------------------------------------------------
-
- Q-28. I can't figure out how to define the main Gopher menu to the server.
-
- A. In the Gopher server JCL, there's a DD statement for DDname
- GGGOPHER. This has to point to a sequential data set (or a member
- of a PDS) containing an MVS Gopher menu. You could also specify the
- main menu (again in the MVS Gopher menu format) as instream (DD *)
- data - if you were running the Gopher server from a batch job, which
- you would do only for testing.
-
- ----------------------------------------------------------------------
-
- Q-29. Why doesn't the Gopher client honor my additional parameters,
- like when I type SERVER(blah)?
-
- A. Did you set up your GOPHER exec to use a different ISPF APPLID?
- There is a misfeature in Gopher V1 and V2 that results from
- the use of the ISPF profile pool to pass values from the GOPHER
- command to the client load module. Gopher V3 finally solved this
- problem by using an in-storage temporary ISPF table to pass the
- values around.
-
- To get around this in V2, stop using the APPLID, or use an APPLID of
- ISR. Or always invoke GOPHER from inside ISPF, rather than typing
- the command from READY mode.
-
- ----------------------------------------------------------------------
-
- Q-30. Why can't I attention out of the Gopher client?
-
- A. Because IBM C/370 is broken. There is a zap for the IBMBLIIA
- load module that will at least let you attention out of the
- C/370 Gopher client. It won't allow you to abort a single
- connection/transfer, though. This didn't happen when we were
- all writing applications in 370 assembler language...
-
- Here's the zap for C/370 V2...
-
- NAME IBMBLIIA IBMBLII1
- VER 2250 0A60
- REP 2250 1BFF
-
- Usual disclaimers apply.
-
- Note: If your edition of IBMBLIIA doesn't match, then look for
- the 0A60 (SVC 96, STAX) macro invocation that gets passed a
- nonzero register 1 value, and zap it as above.
-
- ----------------------------------------------------------------------
-
- Q-31. Why do I have to "S" (select) an item before I can "E" (extract) it?
-
- A. This was fixed in V2R3, which should be out by the
- time you've caught up with all your real work and get around to
- reading this FAQ in your spare time.
-
- ----------------------------------------------------------------------
-
- Q-32. Where's the tutorial?
-
- A. What tutorial? :-)
-
- Use the "About This Gopher" item to find out about using
- the Gopher client. OK, this isn't much of an answer, but
- isn't Gopher a much more pleasant way to read stuff than
- ISPF tutorial panels? Also, there's a TSO HELP member.
-
- ----------------------------------------------------------------------
-
- Q-33. What's the deal with the "w" type?
-
- A. The "w" (WHOIS) type was put in to handle WHOIS-type
- applications, which are like type 7 (index) except that
- they return a file instead of a directory. This type was
- proposed early on and implemented in the UMn Unix Gopher
- via a patch, but nowhere else. Even the implementations
- of "w" in UMn and the MVS Gopher didn't agree with each other.
- The "w" type died out of lack of interest and the general
- belief that gopher+ would handle the same needs. Well,
- gopher+ is still a ways away for the MVS gopher...
-
- Keener eyes among you will claim to notice gopher+ support
- in the V3 MVS gopher. It's only the groundwork for possible
- future support. No promises. Let me just say that if a
- gopher+ client talks to the MVS Gopher server, it might get
- a little more than the V2 Gopher server would have given it.
-
- ----------------------------------------------------------------------
-
- Q-34. How can I debug a Gopher server REXX exec?
-
- A. It ain't easy. The easiest thing is just to run the exec from
- TSO and see what it does, after allocating file SYSTSPRT to
- the terminal (or wherever). Remember, in V2, your exec must be
- writing to SYSTSPRT to return data to the Gopher server.
- But in V3 your exec uses a different means of returning data.
- You must be sure to include the REXX library with all the
- gopher-related execs if you try to test it out at your terminal.
- Best thing is to allocate this same library to SYSEXEC. At least
- with V3, if anything bad happens, it will try to write to the real
- terminal in foreground, and to the file SYSTSPRT in background.
- And since SYSTSPRT will not be swallowed up by Gopher, you might
- actually be able to view it if you include an appropriate DD
- statement in your proc. But don't do that unless you're running
- the single-tasking server, please.
-
- At least the Gopher server log displays return codes from IRXEXEC.
- Return codes from IRXEXEC are documented in the TSO/E REXX
- Reference. Error codes in the range 20000-20099 indicate
- that the REXX interpreter detected a syntax error. The return
- code is 20000 plus the error (presumably the Cowlishaw error number).
-
- Another possibility is to run the exec from your MVS Gopher client
- in "local" (serverless) mode. Allocate your Gopher REXX exec
- library to dd GGEXEC (or use the specification in the GOPHERRC file)
- and specify HOST=- to fire it up. If you are using V2 or earlier,
- make sure that the hacks used to specify the hostname and port are
- appropriate (i.e. they return "-" and "70").
-
- ----------------------------------------------------------------------
-
- Q-35. What hostname and port hacks?
-
- A. Er, see the "About this Gopher" PDS for details. I confess
- that the REXX stuff was complicated and difficult to handle.
- But with V3, it has been redesigned (incompatibly) to make it
- somewhat easier, if still complicated. In any case, you can
- use the sample TSOHELP application as a starting point.
-
- ----------------------------------------------------------------------
-
- Q-36. What MVS file types does the Gopher server support?
-
- A. The Gopher server can serve MVS sequential data sets and
- PDS members. It will also serve PDS's, treating them as
- Gopher directories of members - but this is of limited use,
- as it will display merely the 8-character member names as
- Gopher files.
-
- In addition, the Gopher server recognizes exec:foo as a
- call to a REXX exec called foo, and ftp0: and ftp1: as
- invocations of a Gopher-to-FTP gateway (ftp0 to get a
- remote file, ftp1 to get a remote directory).
-
- With V3, Gopher also supports other file types, including
- binary data. This is mainly useful for the FTP gateway,
- though it does not support compressed files. Also, the MVS
- client can obviously do very little with binary or graphical
- or sound files. The feature will prove highly beneficial for
- clients on other machines that talk to the MVS server. I have
- even pulled down a newer version of the Macintosh TurboGopher
- client through the MVS gopher ftp gateway.
-
- Gopher will not support other MVS file types directly, but
- you can code a REXX exec to access such files (e.g. VSAM
- data sets or DB2 data bases).
-
- ----------------------------------------------------------------------
-
- Q-37: How can I display square brackets while viewing text?
-
- A: By issuing the following command once in ISPF:
-
- For a 3179:
-
- TERM CHAR((X'BA' X'AD') (X'BB' X'BD') (X'AD' X'BA') (X'BD' X'BB'))
-
- For a 3278 or 3180:
-
- TERM CHAR((X'41' X'AD') (X'42' X'BD') (X'AD' X'41') (X'BD' X'42'))
-
- If what you're seeing instead of brackets are vowels with diaeresis
- marks on them, then you are in TN3270, on a 7171, or using a terminal
- type of "APL" - otherwise the brackets would be being translated to
- something incorrect. So you've got half the job done, since the code
- points are right. The other half is to issue that TERMINAL command.
- You can't do it from READY because as soon as ISPF starts up, it will
- trash any VTAM character translations you did before.
-
- If, on the other hand, you're seeing dots, or whatever the "DISP"
- character is set to, then you need a fix to ISPF. You can get the
- package that implements the fix by ftp from ftp.mic.ucla.edu, directory
- /pub/mvs/util, item BRACKETS.
-
- ----------------------------------------------------------------------
-
- Q-38: How can I make the client start up at a specific bookmark file?
-
- A: Just changing the GOPHERRC file to point to the bookmark dataset
- that has the right menu won't work too well, unless you specify the
- LOCAL option when you start up gopher. But you don't want to do
- this - I will explain.
-
- Also, changing the gopher exec is the wrong thing to do. You should
- be able to change only the gopherrc file and still have it do what you
- want it to do.
-
- Did you set localmenu in the read_gopherrc routine? If you didn't,
- then it gets cleared before gopherrc is read. I tried this, setting
- localmenu in the read_gopherrc routine, and it works for me. This is
- not the right approach, though. And there is another problem.
- Specifying LOCAL means that your gopher cannot make any network
- connections, which is not going to make it very useful.
-
- Bookmark support is fairly new, and I do not yet have a good way of
- having your gopherrc file set you up easily to reference a particular
- bookmark. This will take some additional documentation or fixing of
- the code. Meanwhile, here is what to do:
-
- In the gopherrc file, when it is first created, you will see a section
- that says
-
- initial:
- #
- Type=DIRECTORY
- Name=primary (root) gopher menu (or something like that)
- Path=
- Host=mvs.localdomainname.com
- Port=70
- End
-
- Change the above so that Name= reads whatever you want the title to
- display, Path= contains the fully qualified (but without single quotes)
- name of your bookmark file, and (most important to remember this)
- Host=- (hyphen). If you do not change the host=, then you will get an
- error from the gopher server, who will complain that it is not
- authorized to deliver the contents of that directory to your doorstep.
- Host=- insures that the operation on that menu alone is "local" - do
- not specify the LOCAL operand on your gopher invocation.
-
- ----------------------------------------------------------------------
-
- Q-39: Can I set up client items that do anything my users would want?
-
- A: Well, er, you're not supposed to, but - yeah, you can.
- Using a combination of HOST=- (local-mode menu items), private menus
- (bookmarks or gopherrc file hacking) and the EXEC:rexxexecname path
- syntax, you can set up a private gopher that lets you do anything
- you want. Read the "Using Gopher on MVS" stuff in "About This Gopher",
- as well as the HELP file (operand LOCAL).
-
- ./ ENDUP
- ?!
- //CLIST EXEC MDLOAD,BS='6160',TRK1='5',TRK2='1',TO='CLIST'
- //SYSIN DD DATA,DLM='?!'
- ./ ADD NAME=GCALL
- /* REXX. Usage: call gcall "MODULE", "parameter list"
- * Replaces TSO "CALL" command.
- * Module must be in linklist or steplib.
- */
-
- parse arg gmodule, gparam
-
- linklen = d2c(length(gparam),2)
- linkparm = linklen || gparam
-
- address LINKPGM gmodule "LINKPARM"
- return rc
-
- ./ ADD NAME=GCLOSE
- /* REXX. Usage: call gclose
- * Note: we cannot use DD SYSTSPRT in a multitasking environment,
- * so do not invoke this function with a null parameter unless
- * you have no choice.
- */
-
- parse arg gopherargs
-
- file_to_close = gfile(gopherargs) /* defined below */
-
- /* The old way, which required that the caller not queue null lines
- * queue ""
- * "EXECIO * DISKW" file_to_close "(FINIS)"
- */
-
- if queued() = 0 then queue " "
- "EXECIO" queued() "DISKW" file_to_close "(FINIS)"
- iorc = rc
-
- "delstack"
-
- if iorc <> 0 then do
- call gnotify ,
- "GGMVS003 EXECIO return code" iorc "in GCLOSE of" file_to_close
- end
-
- return
-
- gfile: parse arg gopherargs
-
- parse var gopherargs "OUTDD=" outdd ";"
- if outdd = "" then outdd = "SYSTSPRT"
- return outdd
-
- ./ ADD NAME=GHOST
- ghost: parse arg gopherargs
-
- /* Although it should not be necessary with the new MVS Gopher,
- * configure the default host name to match your site.
- */
-
- parse var gopherargs "HOST=" host ";"
- if host = "" then return "MVS.DRAPER.COM"
- return host
-
- ./ ADD NAME=GNOTIFY
- /* REXX. Usage: call gnotify "GGMVSnnn" message-text */
-
- gnotify: parse arg message
- call gcall "XGWTO", message
- return
-
- ./ ADD NAME=GOPEN
- /* REXX. Usage: call gopen */
-
- "newstack"
-
- return
-
- ./ ADD NAME=GOPHER
- /* REXX. GOPHER client. Author: Steve Bacher <seb@draper.com>, with
- * additions by Dwight Cook <SYSDC@uokmvsa.backbone.uoknor.edu>
- */
-
- /* *** Customize the following lines for your installation.
- * If ggmpanel is set to "", it will not be LIBDEF'd.
- */
-
- ggmprefix = "GOPHER"
- ggmpanelsuffix = "PANELS"
- ggmloadsuffix = "LOAD"
- ggmlmod = "GGCLIENT"
- ggmpanel = ggmprefix"."ggmpanelsuffix
- ggmload = ggmprefix"."ggmloadsuffix
- ggmappl = "ISR"
- ggmdefaulthost = "micro.umn.edu" /* initialize GOPHERRC with this */
- ggmdefaulttelnet = "TELNET"
- ggmdefaultbkmgr = "BOOKMGR"
- ggmdefaultdomain = ".DRAPER.COM"
- gophermeister = "" /* TSOid of Gopher's Big Brother */
- xprocavailable = 0 /* set to 1 if XPROC is available */
- crunlibs = "" /* if C run-time must be LIBDEF'd */
-
- trace off
- signal on novalue
- stacked = 0
- libdeffed = 0
- parse arg args
- "ISPQRY"
- if rc > 0 then do
- parse source . . execname . execds .
- if execds = "?" then
- icmd = "%"execname args
- else
- icmd = "EX '"execds"("execname")'" quote(args)
- call startispf ggmappl, icmd
- exit
- end
-
- if xprocavailable then do
-
- save_prompt = prompt("ON")
- "XPROC 0 TEST DEBUG FORCE LOCAL BOOKMARK() INITFILE()
- SERVER() PORT() PATH() DESCRIPTION()"
- if rc <> 0 then exit rc
- call prompt save_prompt
-
- end
-
- else do /* XPROC not available */
-
- bookmark = ""
- initfile = ""
- server = ""
- port = 70
- path =
- description =
- local =
- force =
- test =
- debug =
- uargs = translate(args)
- if wordpos("LOCAL",uargs) > 0 then local = "LOCAL"
- if wordpos("FORCE",uargs) > 0 then force = "FORCE"
- if wordpos("TEST" ,uargs) > 0 then test = "TEST"
- if wordpos("DEBUG",uargs) > 0 then debug = "DEBUG"
-
- /* Limited-function parsing courtesy Dwight Cook */
-
- bookopen = 'BOOKMARK('
- initopen = 'INITFILE('
- servopen = 'SERVER('
- pathopen = 'PATH('
- portopen = 'PORT('
- descopen = 'DESCRIPTION('
- closparn = ')'
- parse var uargs (bookopen) bookmark (closparn)
- parse var uargs (initopen) initfile (closparn)
- parse var uargs (servopen) server (closparn)
- parse var uargs (pathopen) path (closparn)
- parse var uargs (portopen) port (closparn)
- parse var uargs (descopen) description (closparn)
- if port = "" then port = 70
-
- end
-
- signal on failure
- signal on halt
-
- call check_for_other_socket_app
- call read_gopherrc
- call validate_operands
- call libdef
- call let_me_know
- call ggm_dialog
- call unlibdef
-
- cleanup:
- if libdeffed then call unlibdef
- if stacked then "DELSTACK"
- exit
- error:failure:halt:say "GOPHER: Severe lossage."
- say "Statement:" sourceline(sigl)
- exit
-
- /*********************************************************************/
-
- validate_operands:
-
- /*
- * Logic that determines what to display on startup:
- * If gopherrc file does not exist, create it from default
- * (default has everything commented out except for a
- * one-item "initial" menu pointing to the MVS server)
- * Read gopherrc (in case operands need fields therein)
- * Command operands override gopherrc specs:
- * if LOCAL given then server = "-", see below for SERVER(-)
- * if SERVER(host) given then startup host=SERVER, path=PATH, etc.
- * (no gopherrc referenced)
- * if SERVER(-) given then either PATH must be given or
- * the gopherrc's localmenu: must be given,
- * otherwise look at gopherrc
- * if LOCAL given and initial: present then extract startup menu
- * but remember that there will be no server access possible
- * else nothing given, this is an error, barf
- * if no SERVER, look at gopherrc:
- * if initial: given then extract startup menu from there
- * else if localmenu: given then use that menu (SERVER=-)
- * else nothing given, display ISPF panel asking for host/path
- */
-
- if local = "LOCAL" then do
- if server <> "" then do
- say "GOPHER: SERVER cannot be specified when LOCAL is specified."
- exit 12
- end
- server = "-"
- end
-
- if bookmark <> "" then do
- if server <> "" & local = "" then do
- say "GOPHER: SERVER cannot be specified when BOOKMARK is specified."
- exit 12
- end
- if path <> "" then do
- say "GOPHER: PATH cannot be specified when BOOKMARK is specified."
- exit 12
- end
- server = "-"
- if left(bookmark,1) = "'" then path = strip(bookmark,"B","'")
- else do
- tsoprefix = sysvar("SYSPREF")
- if tsoprefix = "" then path = bookmark
- else path = tsoprefix"."bookmark
- end
- if description = "" then description = "Bookmark" path
- end
-
- ggpath = ""
- gghost = ""
- ggport = port
- ggdesc = description
-
- if server <> "" then do
- if server = "-" then do
- gghost = server
- if path <> "" then do
- ggpath = path
- end
- else if localmenu <> "" then do
- ggpath = localmenu
- if ggdesc = "" then ggdesc = "Local Private Gopher Menu"
- end
- else if local = "LOCAL" & initial <> "" then do
- gghost = ""
- call use_initial_spec
- if gghost <> "-" then do
- say "Gopher: Cannot determine path for local access."
- say " Either specify PATH(pathname), activate"
- say " the localmenu: line in" gopherrc ", or set"
- say " the initial: line in" gopherrc "for local access."
- exit 12
- end
- end
- else do
- say "Gopher: Cannot determine path for local access."
- say " Either specify PATH(pathname) or activate"
- say " the localmenu: or initial: line in "gopherrc"."
- exit 12
- end
- end
- else do
- gghost = server
- ggpath = path
- ggdesc = description
- ggport = port
- nop /* use provided server, host, path, etc. */
- end
- end
- else do /* no server given on command */
- if localmenu <> "" then do
- gghost = "-"
- ggpath = localmenu
- if ggdesc = "" then ggdesc = "Local Private Gopher Menu"
- end
- else if initial <> "" then do
- call use_initial_spec
- end
- else do
- /* this is nominally illegal, but should cause gopher to
- display the hackish startup menu */
- gghost = ""
- ggpath = ""
- end
- end
-
- if telnet = "" then ggtelnet = ggmdefaulttelnet
- else ggtelnet = telnet
-
- if bookmgr = "" then ggbkmgr = ggmdefaultbkmgr
- else ggbkmgr = bookmgr
-
- if domain = "" then ggdomain = ggmdefaultdomain
- else ggdomain = domain
-
- return
-
- /*********************************************************************/
-
- use_initial_spec:
-
- if initial = "*temp*" then do
- /* we're eventually not going to do it this way really */
- /* initial_type is ignored - only "DIRECTORY" is valid anyway */
- if initial_name <> "" & ggdesc = "" then ggdesc = initial_name
- if initial_host <> "" & gghost = "" then gghost = initial_host
- if initial_path <> "" & ggpath = "" then ggpath = initial_path
- if initial_port <> "" & ggport = "" then ggport = initial_port
- end
- else do
- ggpath = initial
- if ggdesc = "" then ggdesc = "Local Private Gopher Menu"
- end
-
- return
-
- /*********************************************************************/
-
- read_gopherrc:
-
- localmenu = ""
- localexec = ""
- telnet = ""
- bookmgr = ""
- domain = ""
- initial = ""
- initial_type = ""
- initial_name = ""
- initial_host = ""
- initial_path = ""
- initial_port = ""
- new_gopherrc = 0
- if initfile = "" then gopherrc = "'"userid()".GOPHERRC'"
- else gopherrc = initfile
- gopherrc = "'"userid()".GOPHERRC'"
- gopherdcb = "RECFM(V B) LRECL(255) BLKSIZE(6233) DSORG(PS)"
- gopherrc_status = sysdsn(gopherrc)
- select
- when gopherrc_status = "OK" then nop
- when gopherrc_status = "DATASET NOT FOUND" then do
- address TSO "ALLOC DA("gopherrc") T SP(1 1)" gopherdcb
- if rc <> 0 then do
- say "Error: Cannot create" gopherrc
- exit rc
- end
- new_gopherrc = 1
- end
- otherwise do
- say "Error: Cannot access" gopherrc":" gopherrc_status
- exit 16
- end
- end
-
- address TSO "ALLOC FI(GOPHERRC) DA("gopherrc") OLD REU"
- if rc <> 0 then exit rc
-
- if new_gopherrc = 0 then do
- "EXECIO * DISKR GOPHERRC (FINIS STEM GOPHERRC.)"
- execiorc = rc
- if execiorc <> 0 then do
- say "Error: Cannot read" gopherrc
- address TSO "FREE FI(GOPHERRC)"
- exit execiorc
- end
- if gopherrc.0 = 0 then new_gopherrc = 1
- end
-
- if new_gopherrc then call initialize_gopherrc
-
- address TSO "FREE FI(GOPHERRC)"
-
- collecting_initial = 0
- do i = 1 to gopherrc.0
- gline = gopherrc.i
- if gline = "" then iterate
- if left(gline,1) = '#' then iterate
- parse var gline ghead ":" gtext
- ghead = translate(strip(ghead,"B"))
- gtext = strip(gtext,"B")
- if collecting_initial then do
- parse var gline ghead "=" gtext
- ghead = translate(strip(ghead,"B"))
- gtext = strip(gtext,"B")
- select
- when ghead = "TYPE" then initial_type = gtext
- when ghead = "NAME" then initial_name = gtext
- when ghead = "PATH" then initial_path = gtext
- when ghead = "HOST" then initial_host = gtext
- when ghead = "PORT" then initial_port = gtext
- when ghead = "END" then do
- collecting_initial = 0
- initial = "*temp*"
- end
- otherwise do
- say "Error in "gopherrc": INITIAL: not terminated by END"
- say "Line where error was detected:"
- say gline
- exit 8
- end
- end
- end
- else select
- when ghead = "LOCALMENU" then localmenu = gtext
- when ghead = "LOCALEXEC" then localexec = gtext
- when ghead = "TELNET" then telnet = gtext
- when ghead = "BOOKMGR" then bookmgr = gtext
- when ghead = "DOMAIN" then domain = gtext
- when ghead = "INITIAL" then do
- if gtext = "" then collecting_initial = 1
- else initial = gtext
- end
- otherwise do
- say "Warning, gopherrc field ignored:" ghead
- end
- end
- end
-
- return
-
- /*********************************************************************/
-
- ggm_dialog:
-
- tbputvars = "GGHOST GGPORT GGPATH GGDESC GGDOMAIN GGTELNET GGBKMGR"
-
- address ISPEXEC "TBCREATE GOPHERVT NAMES("tbputvars") NOWRITE REPLACE"
- if rc > 4 then do; call ispf_error rc; exit rc; end
- address ISPEXEC "TBADD GOPHERVT"
- if rc > 8 then do; call ispf_error rc; exit rc; end
-
- parm = ""
- if test = "TEST" then parm = parm "-t"
- if debug = "DEBUG" then parm = parm "-d"
- if local = "LOCAL" then parm = parm "-l"
- if gghost <> "" then parm = parm "-q"
-
- zerrmsg = ""
- zerrsm = ""
- zerrlm = ""
-
- address ISPEXEC "VPUT (ZERRMSG ZERRSM ZERRLM)"
-
- if ggmappl = "" then applsource = ""
- else applsource = "NEWAPPL("ggmappl") PASSLIB"
-
- if ggmload = "" then selstring = "PGM("ggmlmod") PARM("parm")"
- else selstring = "CMD(CALL '"ggmload"("ggmlmod")'" quote(parm)")"
-
- address ISPEXEC "SELECT" applsource selstring
-
- if rc <> 0 then say "Return code from" ggmlmod "program is" rc
-
- /* Table was supposed to be closed in the program, but just in case */
-
- address ISPEXEC "CONTROL ERRORS RETURN"
- address ISPEXEC "TBCLOSE GOPHERVT" /* don't bother checking rc */
-
- address ISPEXEC "VGET (ZERRSM ZERRLM)"
- if zerrsm <> "" then do
- say zerrmsg":" zerrsm
- say zerrlm
- end
-
- return
-
- /*********************************************************************/
-
- libdef:
- if crunlibs <> "" then do
- address ISPEXEC "LIBDEF ISPLLIB DATASET ID("crunlibs")"
- if rc <> 0 then do; call ispf_error rc; exit rc; end
- end
- if ggmpanel <> "" then do
- address ISPEXEC "LIBDEF ISPPLIB DATASET ID('"ggmpanel"')"
- if rc <> 0 then do; call ispf_error rc; exit rc; end
- end
- if localexec <> "" then do
- address TSO "ALLOC FI(GGEXEC) SHR REU DA('"localexec"')"
- if rc <> 0 then exit rc
- end
- libdeffed = 1
- return
-
- /*********************************************************************/
-
- unlibdef:
- if localexec <> "" then do
- address TSO "FREE FI(GGEXEC)"
- end
- if ggmpanel <> "" then do
- address ISPEXEC "LIBDEF ISPPLIB DATASET"
- if rc <> 0 then call ispf_error rc
- end
- if crunlibs <> "" then do
- address ISPEXEC "LIBDEF ISPLLIB DATASET"
- if rc <> 0 then call ispf_error rc
- end
- libdeffed = 0
- return
-
- /*********************************************************************/
-
- initialize_gopherrc:
-
- say "Initializing new GOPHERRC file "gopherrc"..."
- do i = sigl while sourceline(i) <> "_BEGIN_"
- end
- gx = 0
- do i = i+1 by 1
- gline = sourceline(i)
- if gline = "_END_" then leave
- gpos = pos("ggmdefaulthost",gline)
- if gpos > 0 then gline = substr(gline,1,gpos-1) || ggmdefaulthost
- gpos = pos("ggmdefaulttelnet",gline)
- if gpos > 0 then gline = substr(gline,1,gpos-1) || ggmdefaulttelnet
- gpos = pos("ggmdefaultbkmgr",gline)
- if gpos > 0 then gline = substr(gline,1,gpos-1) || ggmdefaultbkmgr
- gpos = pos("ggmdefaultdomain",gline)
- if gpos > 0 then gline = substr(gline,1,gpos-1) || ggmdefaultdomain
- gx = gx + 1
- gopherrc.gx = gline
- end
- gopherrc.0 = gx
- "EXECIO * DISKW GOPHERRC (FINIS STEM GOPHERRC.)"
- say "New GOPHERRC file initialized."
-
- return
-
- /*
-
- _BEGIN_
- #
- #
- # Default "gopherrc" file, created by the MVS Gopher client.
- #
- # Uncomment desired fields by removing the initial "# " from them.
- #
- # Beware - the Gopher client may update this file with bookmarks.
- # You can delete it at any time and it will be recreated
- # from the default settings, but you'll lose your bookmarks.
- #
- ######################################################################
- #
- # If you want local (serverless) gopher access, then use the following
- # lines, specifying full qualified (no quotes) data set names:
- #
- # localmenu: name_of_initial_gopher_menu
- # localexec: name_of_pds_of_rexx_execs
- #
- # Specifying localmenu: is equivalent to specifying an initial: section
- # with host set to "-" and path set to the value of localmenu.
- #
- # You cannot use your own REXX execs, however, unless you specify
- # localexec: as above. You don't need one to use the other, though.
- #
- ######################################################################
- #
- # The following is used by the Gopher client at startup to determine
- # how the initial menu will appear.
- #
- # You may want to change the host to the one appropriate for your site.
- #
- initial:
- #
- Type=DIRECTORY
- Name=Primary (Root) Gopher Menu
- Path=
- Host=ggmdefaulthost
- Port=70
- End
- #
- # Alternatively, if you want your own private Gopher data:
- #
- # initial:
- #
- # Type=0
- # Name=My Own Private Gopherhole
- # Path=userid.GOPHER.MENU
- # Host=-
- # End
- #
- # In which case you should create a data set called userid.GOPHER.MENU
- # (or whatever name you choose that appears in the "Path=" line above)
- # that looks like this. (NOT in the gopherrc file!)
- #
- #
- # gopher_menu
- #
- # TYPE=DIRECTORY
- # NAME=Public GOPHER Server at ggmdefaulthost
- # PATH=
- # HOST=ggmdefaulthost
- # END
- #
- # TYPE=DIRECTORY
- # NAME=Private GOPHER
- # PATH=userid.ANOTHER.GOPHER.MENU
- # HOST=-
- # END
- #
- # and then you need yet another menu, similar in format to this one,
- # in userid.ANOTHER.GOPHER.MENU. Get the idea?
- #
- ######################################################################
- #
- # These fields are used by the Gopher client to set defaults.
- #
- Telnet: ggmdefaulttelnet
- Bookmgr: ggmdefaultbkmgr
- Domain: ggmdefaultdomain
- #
- ######################################################################
- _END_
-
- */
-
- /*********************************************************************/
-
- check_for_other_socket_app:
-
- if local = "LOCAL" then return
-
- call nnmfiucv /* FIND IUCVMULT in another PIE MultiTSO session */
-
- if result = 0 then return
-
- say,
- "A TCP/IP socket application appears active in another PIE session."
- if force = "FORCE" then do
- say "Proceeding anyhow, because you said FORCE."
- return
- end
- say "To proceed at this point would be potentially disastrous."
- say "If you want to use GOPHER anyway, use one of these operands:"
- say " FORCE - if I'm mistaken and it's really safe to make a"
- say " TCP/IP connection."
- say " LOCAL - if you just want local (serverless) access."
- say "Terminating."
-
- exit 16
-
- /*********************************************************************/
-
- ispf_error: parse arg ispfrc
-
- say "GOPHER: ISPF dialog service error detected on line" sigl
- say sourceline(sigl)
- say
- say zerrmsg":" zerrsm
- say zerrlm
- say
- say "Return code =" ispfrc
- say
-
- return ispfrc
-
- /*********************************************************************/
-
- /*
- * The following function starts ISPF from READY mode.
- * Beware: splitting the screen starts up an identical copy of the
- * application, which may not be desirable.
- */
-
- startispf: parse arg startappl, startcmd
- if startappl = "" then,
- "ISPSTART CMD("startcmd")"
- else,
- "ISPSTART NEWAPPL("startappl") CMD("startcmd")"
- return
-
- /* The following function implements Big Brother mode. */
-
- let_me_know:
- if gophermeister = "" | gophermeister = userid() then return
- parse source . . execname . execds .
- call outtrap "X."
- address TSO,
- "SEND" quote(execds"("execname")" date("U") time()" "),
- "U("gophermeister") LOGON"
- call outtrap "OFF"
- return
-
- /* The following function enquotes a string. */
-
- quote: parse arg string
- ix = 1
- do forever
- ix = pos("'",string,ix)
- if ix = 0 then return "'"string"'"
- string = insert("'",string,ix)
- ix=ix+2
- end
-
- ./ ADD NAME=GPORT
- gport: parse arg gopherargs
-
- /* Although it should not be necessary with the new MVS Gopher,
- * configure the default port number to match your site.
- */
-
- parse var gopherargs "PORT=" port ";"
- if port = "" then return "1570"
- return port
-
- ./ ADD NAME=GRAB
- /* GRAB: Gopher REXX Allocator in Batch
- * Usage: ddname = grab(dsname,disp{,ddname})
- */
- trace off
- signal on novalue
-
- parse arg dsname, disp, ddname
- dsname = strip(dsname,"B")
- disp = strip(disp ,"B")
- ddname = strip(ddname,"B")
- msg1 = ""
- msg2 = ""
-
- dsname = strip(dsname,"B","'")
-
- do forever
- address linkmvs "XGALLOC DSNAME DDNAME DISP MSG1 MSG2"
- if rc <> 0 then do
- if pos(" IN USE",msg1) > 0 | pos(" IN USE",msg2) > 0 then do
- call gsleep 2
- iterate
- end
- if msg1 <> "" then call gnotify "GGMVS004" msg1
- if msg2 <> "" then call gnotify "GGMVS005" msg2
- end
- leave
- end
- return ddname
-
- gsleep: parse arg seconds
- call gnotify "GGMVS008" ,
- "GRAB:" dsname "in use. Retrying in" seconds "seconds..."
- call gcall "XGSLEEP", seconds
- return
- ./ ADD NAME=GRABTEMP
- /* GRAB: Gopher REXX Allocator in Batch to Touch Empty Memory Pages
- * Usage: ddname = grabtemp({ddname})
- */
- trace off
- signal on novalue
-
- parse arg ddname
-
- dsname = ""
- disp = "NEW"
- ddname = strip(ddname,"B")
- msg1 = ""
- msg2 = ""
-
- address linkmvs "XGALLOC DSNAME DDNAME DISP MSG1 MSG2"
- if rc <> 0 then do
- if msg1 <> "" then call gnotify "GGMVS004" msg1
- if msg2 <> "" then call gnotify "GGMVS005" msg2
- end
- return ddname
- ./ ADD NAME=GREAD
- /* REXX. Usage: call gread ddname
- */
-
- parse arg ddname
-
- line. =
- line.0 =
-
- "EXECIO * DISKR" ddname "(FINIS STEM LINE.)"
-
- do i = 1 to line.0
- if line.i = "" then queue " "; else queue line.i
- end
-
- return
-
- ./ ADD NAME=GTSOTRAP
- /* REXX */
-
- parse arg tsocommand, gopherargs
-
- x = outtrap("LINE.")
- address TSO tsocommand
- arc = rc
- x = outtrap("OFF")
- call gopen gopherargs
- do i = 1 to line.0
- if line.i = "" then queue " ";else queue line.i
- end
- call gclose gopherargs
-
- return arc
- ./ ADD NAME=HOSTNAME
- /* REXX */
-
- parse arg gopherargs
-
- return ghost(gopherargs)
-
- ./ ADD NAME=NNMFIUCV
- /* REXX. This exec scans the job pack queues for IUCVMULT and returns
- * with an error code if IUCVMULT is already loaded under a
- * different TCB. This can only happen under PIE MultiTSO or a
- * similar product that makes multiple job step TCB's.
- */
-
- trace off
- signal on novalue
-
- search_name = "IUCVMULT"
- count = 0
- foundtcb. = ""
- current_tcb = getword24("21C")
- current_job_step_tcb = getword24(current_tcb,"7C")
- current_ascb = getword24("224")
- current_asxb = getword31(current_ascb,"6C")
- first_tcb = getword24(current_asxb,"4")
- tcb = first_tcb
- motherflag = 0
- do forever
- if motherflag = 0 then do
- call process
- daughter_tcb = getword24(tcb,"88")
- if daughter_tcb \= "00000000" then do
- tcb = daughter_tcb
- iterate
- end
- end
- motherflag = 0
- sister_tcb = getword24(tcb, "80")
- if sister_tcb \= "00000000" then do
- tcb = sister_tcb
- iterate
- end
- mother_tcb = getword24(tcb, "84")
- if mother_tcb \= "00000000" then do
- tcb = mother_tcb
- motherflag = 1
- iterate
- end
- leave
- end
-
- if count = 0 then return 0
- problem = 0
- do i = 1 to count
- if foundtcb.i = current_job_step_tcb then do
- /*
- say search_name "is already loaded under current TCB at "foundtcb.i"."
- */
- end
- else do
- /*
- say search_name "is loaded under different TCB at "foundtcb.i"."
- */
- problem = 1
- end
- end
-
- if problem = 1 then return 1
-
- else return 0
-
- process:
-
- jpq = getword31(tcb,"2C")
- cde = jpq
- do while cde \= "00000000"
- cde_contents = storage(cde,32)
- cde_name = substr(cde_contents,9,8)
- cde_epa = substr(cde_contents,9,8)
- if search_name = cde_name then do
- count = count + 1
- foundtcb.count = tcb
- end
- cde = getword31(cde,"0")
- end
-
- return
-
- getword31: parse arg addr, offset
- temp1 = x2d(addr)
- if offset = "" then temp2 = 0
- else temp2 = x2d(offset)
- return c2x(storage(d2x(temp1+temp2),4))
-
- getword24: parse arg addr, offset
- temp1 = x2d(addr)
- if offset = "" then temp2 = 0
- else temp2 = x2d(offset)
- return "00"c2x(storage(d2x(temp1+temp2+1),3))
-
- ./ ADD NAME=PORT
- /* REXX */
-
- parse arg gopherargs
-
- return gport(gopherargs)
-
- ./ ADD NAME=REXXTEST
- /* REXX */
-
- parse arg args, gopherargs
- parse version rexx_version
- parse source rexx_source
-
- call gopen gopherargs
-
- queue "PARSE VERSION returns:" rexx_version
- queue "PARSE SOURCE returns:" rexx_source
- queue "Argument 1 is........." args
- queue "Gopherargs are........" gopherargs
-
- call gclose gopherargs
-
- return
-
- ./ ADD NAME=TSOHELP
- /* REXX */
-
- /* This exec provides a sample TSO HELP application.
- The gopher menu item will look something like this:
-
- TYPE=DIRECTORY
- NAME=TSO HELP
- PATH=EXEC:TSOHELP
- HOST=+
- END
-
- where "TSOHELP" is the name of this exec.
-
- This exec generates a series of lower-level menus, giving the user
- a choice of how much help data to search (IBM only, local installation
- help, etc.). This particular sample is Draper Lab's own, so you will
- need to change it.
-
- */
-
- trace off
- signal on novalue
-
- host = hostname()
- port = "70"
- tab = '05'x
-
- helpfiles. = "'SYS1.HELP'"
- helpfiles.sys1 = "'SYS1.HELP'"
- helpfiles.draper = "'CSD.CMD.HELP' 'CSD.PP.HELP' 'SYS1.HELP'"
- helpfiles.proglib = "'PROGLIB.CMD.HELP'"
-
- parse arg helplib command type extra
-
- if helplib = "" then,
- call display_top_menus
- else call set_up_help helplib,command,type,extra
-
- return 0
-
- /*------------------------------------------------------------------*/
-
- display_top_menus:
-
- call start_output
- call menu_out "SYS1", "COMMANDS","DIRECTORY","Regular IBM TSO Help"
- call menu_out "DRAPER","COMMANDS","DIRECTORY","IBM and Draper TSO Help"
- call menu_out "PROGLIB","PROGLIB" ,"DIRECTORY","PROGLIB TSO Help"
- call end_output
-
- return
-
- /*------------------------------------------------------------------*/
-
- set_up_help: parse arg helplib,command,type,extra
-
- call outtrap "TSO."
- "ALLOC FI(SYSHELP) SHR REU DA("helpfiles.helplib")"
- allocrc = rc
- call outtrap "OFF"
- if allocrc <> 0 then do
- call start_output
- do i = 1 to tso.0
- call menu_out "ERROR","ERROR","DIRECTORY",tso.i
- end
- call end_output
- end
- else do
- select
- when type = "FILE" then call specific_help command,extra
- when type = "DIRECTORY" then call general_help command,extra
- when type = "INDEX" then call index_help extra
- otherwise call specific_help command
- end
-
- return
-
- /*------------------------------------------------------------------*/
-
- index_help:
-
- /* This intermediate one-element directory is necessary because
- * the Gopher INDEX format only returns directories, not files.
- */
-
- parse upper arg commands
- call start_output
- do while commands <> ""
- parse var commands command commands
- call menu_out helplib,command,"FILE","Complete help for" command
- call menu_out helplib,command,"FILE","Function help only","FUNCTION"
- call menu_out helplib,command,"FILE","Syntax help only","SYNTAX"
- call menu_out helplib,command,"FILE","Operands help only","OPERANDS"
- end
- call end_output
-
- return
-
- /*------------------------------------------------------------------*/
-
- general_help:
-
- parse arg command,extra
-
- call get_help_text command,extra
-
- call start_output
-
- call menu_out helplib,"*","INDEX","Help for a specific TSO command"
-
- do i = 1 to help.0
- parse var help.i helpname helpdesc
- if helpdesc <> "" & ,
- length(helpname) <= 8 & ,
- helpname < "0" & ,
- verify(helpname,"ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789W#$") = 0 ,
- then do
-
- /*
- * Draper help has a series of "$..." members which are like
- * sublevel COMMANDS members. This hack supports that.
- */
-
- if left(helpname,1) = "$" then do
- call menu_out helplib,helpname,"DIRECTORY",helpdesc
- end
- else do
- call menu_out helplib,helpname,"FILE",helpdesc
- end
- end
- end
-
- call end_output
-
- return
-
- /*------------------------------------------------------------------*/
-
- specific_help:
-
- parse arg command,extra
-
- call get_help_text command,extra
-
- call start_output
-
- do i = 1 to help.0
- call text_output help.i
- end
-
- call end_output
-
- return
-
- /*------------------------------------------------------------------*/
-
- get_help_text:
-
- parse arg helpcmd,helpargs
-
- help. =
-
- call outtrap "HELP."
-
- address TSO "HELP" helpcmd helpargs
-
- call outtrap "OFF"
-
- return
-
- /*------------------------------------------------------------------*/
-
- menu_out: parse arg mlib,mname,mtype,mdesc,mops
-
- select
- when mtype = "FILE" then gtype = "0"
- when mtype = "DIRECTORY" then gtype = "1"
- when mtype = "INDEX" then gtype = "7"
- otherwise do
- call menu_out "ERROR","ERROR","DIRECTORY", "Unknown type:" mtype
- end
- end
-
- gname = left(mname,9)"--" mdesc
- gpath = "EXEC:TSOHELP" mlib mname mtype mops
- out = gtype || gname || tab || gpath || tab || host || tab || port
- queue out
-
- return
-
- /*------------------------------------------------------------------*/
-
- text_output: parse arg text
-
- if text = "" then queue " "
- else queue text
-
- return
-
- /*------------------------------------------------------------------*/
-
- start_output:
-
- "newstack"
-
- return
-
- /*------------------------------------------------------------------*/
-
- end_output:
-
- queue ""
-
- "EXECIO * DISKW SYSTSPRT (FINIS)"
-
- "delstack"
-
- return
-
- ./ ADD NAME=UNGRAB
- /* UNGRAB: Utterly Negate Gopher REXX Allocator in Batch
- * Usage: call ungrab ddname {,FREE/DELETE}
- */
- trace off
- signal on novalue
-
- parse arg ddname
- dsname = ""
- disp = ""
- if disp = "" then disp = "FREE"
- msg1 = ""
- msg2 = ""
-
- address linkmvs "XGALLOC DSNAME DDNAME DISP MSG1 MSG2"
- if rc <> 0 then do
- if msg1 <> "" then call gnotify "GGMVS006" msg1
- if msg2 <> "" then call gnotify "GGMVS007" msg2
- return rc
- end
- return 0
- ./ ENDUP
- ?!
- //H EXEC MDLOAD,BS='6160',TRK1='5',TRK2='1',TO='H'
- //SYSIN DD DATA,DLM='?!'
- ./ ADD NAME=GG
-
- /********************************************************************/
- /* */
- /* Copyright (c) The Charles Stark Draper Laboratory, 1992, 1993 */
- /* GOPHER server due to Shawn Hart at the University of Delaware. */
- /* GOPHER client due to Steve Bacher at Draper Laboratory. */
- /* SAS modifications due to Dale Ingold at SAS Institute, Inc. */
- /* */
- /* This software is provided on an "AS IS" basis. All warranties, */
- /* including the implied warranties of merchantability and fitness, */
- /* are expressly denied. */
- /* */
- /* Provided this copyright notice is included, this software may */
- /* be freely distributed and not offered for sale. */
- /* */
- /* Changes or modifications may be made and used only by the maker */
- /* of same, and not further distributed. Such modifications should */
- /* be mailed to the author for consideration for addition to the */
- /* software and incorporation in subsequent releases. */
- /* */
- /********************************************************************/
-
- /* --------------------- "gg.h" include member --------------------- */
-
- #pragma linkage(ispexec,OS)
- #pragma linkage(isplink,OS)
- #pragma linkage(ikjeff18,OS)
- #pragma linkage(ikjeftsr,OS)
- #pragma linkage(irxexec,OS)
- #pragma linkage(cmxlate,OS)
-
- /****** Installation-customized defines. *****************************/
-
- #include "gguser.h"
-
- #ifndef C370V1
- #ifndef C370V2
- #ifndef SASC
- install_error_neither_C370V1_C370V2_nor_SASC_was_defined;
- #endif
- #endif
- #endif
-
- #ifndef TCPIPV1
- #ifndef TCPIPV2
- #ifndef SNSTCPIP
- install_error_neither_TCPIPV1_TCPIPV2_nor_SNSTCPIP_was_defined;
- #endif
- #endif
- #endif
-
- #ifndef ISPFV2
- #ifndef ISPFV3
- install_error_neither_ISPFV2_nor_ISPFV3_was_defined;
- #endif
- #endif
-
- #define MVS
-
- #ifdef SNSTCPIP
- #undef USE_CMXLATE
- #ifndef I370
- #define SNSC370
- #endif
- #endif
-
- #ifdef I370
- #undef USE_CMXLATE
- #endif
-
- /****** Clean up compiler warnings BEFORE time.h gets 'em ************/
-
- #ifndef SASC
- #define localtime LOCALTIM
- #endif
-
- /****** Include all header files that are necessary. *****************/
-
- #ifndef SNSTCPIP
- #include <manifest.h>
- #include <sys/types.h>
- #include <netinet/in.h>
- #include <sys/ioctl.h>
- #include <tcperrno.h>
- #include <fcntl.h>
- #endif
-
- #include <sys/socket.h>
- #include <netdb.h>
- #include <sys/uio.h>
- #include <ctype.h>
- #include <errno.h>
- #include <limits.h>
- #include <setjmp.h>
- #include <stdio.h>
- #include <stdarg.h>
- #include <stdlib.h>
- #include <string.h>
- #include <stddef.h>
- #include <time.h>
-
- #ifdef SNSTCPIP
- #include <acs.h>
- #include <inet.h>
- #include <sockcfg.h>
- #include <serrno.h>
- #endif
-
- #ifndef SASC
- #include <ctest.h>
- #endif
-
- #ifdef C370V2
- #undef ENOMEM
- #include <mtf.h>
- #endif
-
- #ifdef SASC
- #include "ggsasc.h"
- #endif
-
- /****** Version-dependent stuff **************************************/
-
- #ifdef C370V1
- #undef FETCH
- #endif
-
- #ifdef C370V2
- #define FETCH
- #endif
-
- #ifdef TCPIPV1
- #define TCP_DEBUG tcp_debug
- #endif
-
- #ifdef TCPIPV2
- #define TCP_DEBUG sock_debug
- #endif
-
- #ifdef SNSTCPIP
- #define TCP_DEBUG /* I don't know how to debug in SNS */
- #endif
-
- #ifdef GOPHER_DEBUG
- #define TCP_DEBUG_ON TCP_DEBUG(1)
- #define TCP_DEBUG_OFF TCP_DEBUG(0)
- #else
- #define TCP_DEBUG_ON /* */
- #define TCP_DEBUG_OFF /* */
- #endif
-
- /****** Preprocessor bookkeeping *************************************/
-
- #define Bool char
- #define Fool unsigned int /* for function arguments */
- #ifndef TRUE
- #define TRUE 1
- #endif
- #ifndef FALSE
- #define FALSE 0
- #endif
-
- #define GOPHER_FILE '0'
- #define GOPHER_DIRECTORY '1'
- #define GOPHER_MENU '1'
- #define GOPHER_CSO '2'
- #define GOPHER_ERROR '3'
- #define GOPHER_MAC_BINHEX '4'
- #define GOPHER_DOS_BINARCH '5'
- #define GOPHER_UUENCODE '6'
- #define GOPHER_WAIS '7'
- #define GOPHER_INDEX '7'
- #define GOPHER_TELNET '8'
- #define GOPHER_TN3270 'T'
- #define GOPHER_BINARY '9'
- #define GOPHER_REDUNDANT '+'
- #define GOPHER_WHOIS 'w'
- #define GOPHER_IMAGE 'I'
- #define GOPHER_BOOKMANAGER 'b'
- #define GOPHER_COMMENT 'i'
- #define GOPHER_UNKNOWN '\0'
- #define COMMANDSIZE 12
- #define INTERNET_SIZE 256
- #define RBUFSIZE 512
- #define OUTBUFSIZE 1024
- #define READ_BYTES 1024
- #define SERVER_BUF_MSGSIZE 1024
- #define CLIENT_BUF_MSGSIZE 1024
- #define TEXT_BYTES 1024
- #define GOPHER_PORT_NUMBER 70
- #define GOPHER_HOST_LENGTH MAXHOSTNAMELEN
- #define GOPHER_PATH_LENGTH 512
- #define GOPHER_DESC_LENGTH 256
- #define SOCKET_GETCHAR_ERROR (-1)
- #define SOCKET_NO_MORE (-2)
- #define SOCKET_READ_NOTHING (-3)
- #define NO_VALUE (-1)
- #define OUT_PLUS (-2)
- #define Rstruc register struct
- #define RGGCB register GGCB
- #define RRECV register RECV
- #define REXTR register EXTRACTION
- #define RINFO register GOPHERINFO
- #define RCONN register CONNECTION
- #define EQUAL !strcmp
- #define UNEQUAL strcmp
- #define COPY(A,B) strncpy((A),(B),sizeof(A)-1)
- #define DUMMY_FILE_POINTER (FILE *)(-1)
- #define MAX_INT (int)0x7fffffff
- #define LOCATE_INT (int)0x7ffffffe
- #define CARRIAGE_RETURN '\r'
- #define FIND_NEXT 'N'
- #define FIND_FIRST 'F'
- #define FIND_LAST 'L'
- #define FIND_PREV 'P'
- #define FIND_ALL 'A'
- #define FIND_CHARS '\0'
- #define FIND_WORD 'W'
- #define FIND_PREFIX 'P'
- #define FIND_SUFFIX 'S'
- #define FIND_CAPS '\0'
- #define FIND_ASIS 'A'
- #define FIND_HEX 'X'
- #define FIND_GENERIC 'P'
- #define FIND_BADFORM '\0'
- #define FIND_UNQUOTED 'U'
- #define FIND_QUOTED 'Q'
- #define FIND_C 'C'
- #define FIND_X 'X'
- #define FIND_T 'T'
- #define FIND_P 'P'
- #define DATAOUT_LOW 0x01
- #define DATAOUT_HIGH 0x02
- #define DATAIN_LOW 0x03
- #define DATAIN_HIGH 0x04
- #define DATAOUT_BLUE DATAOUT_LOW
- #define DATAOUT_GREEN 0x05
- #define DATAOUT_PINK 0x06
- #define DATAOUT_RED 0x07
- #define DATAOUT_TURQ 0x08
- #define DATAOUT_WHITE DATAOUT_HIGH
- #define DATAOUT_YELLOW 0x09
- #define DATAIN_BLUE 0x0a
- #define DATAIN_GREEN DATAIN_LOW
- #define DATAIN_PINK 0x0b
- #define DATAIN_RED DATAIN_HIGH
- #define DATAIN_TURQ 0x0c
- #define DATAIN_WHITE 0x0d
- #define DATAIN_YELLOW 0x0e
-
- #ifdef I370
- #define LINE_FEED 0x15
- #define EtoA htoncs
- #define AtoE ntohcs
- #else
- #define LINE_FEED 0x25
- #ifdef SNSTCPIP
- #define EtoA etoa
- #define AtoE atoe
- #else
- #define EtoA(x) ebcdictoascii[x]
- #define AtoE(x) asciitoebcdic[x]
- #define ebcdictoascii ebcdicto
- #define asciitoebcdic asciitoe
- #endif
- #endif
-
- #ifdef USE_CMXLATE
- #define EBCDIC_TO_ASCII(A,B) cmxlate((A),ebcdictoascii,(B))
- #define ASCII_TO_EBCDIC(A,B) cmxlate((A),asciitoebcdic,(B))
- #else
- #ifdef SNSC370
- #define EBCDIC_TO_ASCII(A,B) EtoA(A,B)
- #define ASCII_TO_EBCDIC(A,B) AtoE(A,B)
- #else
- #define EBCDIC_TO_ASCII(A,B) {int _i; \
- for (_i=0; _i<(B); ++_i) \
- (A)[_i] = EtoA((A)[_i]); \
- }
- #define ASCII_TO_EBCDIC(A,B) {int _i; \
- for (_i=0; _i<(B); ++_i) \
- (A)[_i] = AtoE((A)[_i]); \
- }
- #endif
- #endif
-
- #ifdef TCPIPV1
- #define REPORT_TCP_ERROR(A) /* */
- #endif
-
- #ifdef TCPIPV2
- #define REPORT_TCP_ERROR(A) tcperror(A)
- #endif
-
- #ifdef SNSTCPIP
- #define REPORT_TCP_ERROR(A) fprintf(stderr,\
- "\nTCP error on %s: errno = %d\n",\
- A,GET_ERRNO)
- #endif
-
- #ifdef SNSC370
- #define Accept(A,B,C) accept((A),(struct sockaddr *)(B),(C))
- #define Bind(A,B,C) bind((A),(struct sockaddr *)(B),(C))
- #define Connect(A,B,C) connect((A),(struct sockaddr *)(B),(C))
- #define Gethostbyaddr(A,B,C) gethostbyaddr((char *)(A),(B),(C))
- #define Getpeername(A,B,C) getpeername((A),(struct sockaddr *)(B),(C))
- #define Getsockname(A,B,C) getsockname((A),(struct sockaddr *)(B),(C))
- #define Getsockopt(A,B,C,D,E) getsockopt((A),(B),(C),(char *)(D),(E))
- #define EWOULDBLOCK (ESWOULDBLOCK+s0skcfg.errnobase)
- #else
- #define Accept accept
- #define Bind bind
- #define Connect connect
- #define Gethostbyaddr gethostbyaddr
- #define Getpeername getpeername
- #define Getsockname(A,B,C) getsockname((A),(char *)(B),(C))
- #define Getsockopt getsockopt
- #endif
-
- #ifdef FETCH
- #define ISPLINK (gp->isplink_pointer)
- #define ISPEXEC (gp->ispexec_pointer)
- #else
- #define ISPLINK isplink
- #define ISPEXEC ispexec
- #endif
-
- #ifdef ISPFV3
- #define ZERRLM_SIZE 513
- #else
- #define ZERRLM_SIZE 73
- #endif
-
- #define GOPHER_MSGID_OK "GGMVS001"
- #define GOPHER_MSGID_ERROR "GGMVS002"
-
- #define NOTIFY_MSG 1
- #define WARNING_MSG 2
- #define CRITICAL_MSG 3
-
- #define WARN1(X) GGpmsg(gp,NOTIFY_MSG,NULL,X)
- #define WARN2(X,Y) GGpmsg(gp,NOTIFY_MSG,NULL,X,Y)
- #define WARN3(X,Y,Z) GGpmsg(gp,NOTIFY_MSG,NULL,X,Y,Z)
- #define WARN4(X,Y,Z,W) GGpmsg(gp,NOTIFY_MSG,NULL,X,Y,Z,W)
- #define ERR1(X) GGpmsg(gp,WARNING_MSG,NULL,X)
- #define ERR2(X,Y) GGpmsg(gp,WARNING_MSG,NULL,X,Y)
- #define ERR3(X,Y,Z) GGpmsg(gp,WARNING_MSG,NULL,X,Y,Z)
- #define ERR4(X,Y,Z,W) GGpmsg(gp,WARNING_MSG,NULL,X,Y,Z,W)
- #define CRIT1(X) GGpmsg(gp,CRITICAL_MSG,NULL,X)
- #define CRIT2(X,Y) GGpmsg(gp,CRITICAL_MSG,NULL,X,Y)
- #define CRIT3(X,Y,Z) GGpmsg(gp,CRITICAL_MSG,NULL,X,Y,Z)
-
- #define GETMAIN(P,T,S,F) GGgetm(gp,(char **)&(P),(sizeof(T))*(S),F)
- #define FREEMAIN(P,F) if (P) {GGfreem(gp,(char *)P,F);}
- #define GOPHERSEND(X,Y) if (!(GGesrvr(X,Y),\
- GGsockt(X,Y))) return FALSE
- #define CLEAR(X) memset(X,0,sizeof(*X))
- #define ISPF(X) GGispf(gp,X)
- #define VGET(X,Y) GGivget(gp,X,Y,sizeof(Y))
- #define VGETS(X,Y,Z) GGivget(gp,X,Y,Z)
- #define VPUT(X,Y) GGivput(gp,X,Y,-1)
- #define VPUTS(X,Y,Z) GGivput(gp,X,Y,Z)
- #define IGET(X) GGiget(gp,X)
- #define IPUT(X,Y) {char _iput[16];\
- sprintf(_iput,"%d",(Y));\
- VPUT(X,_iput);}
- #ifndef I370
- #define WRITE_FILEMODE "w,recfm=vb,lrecl=259,blksize=6233"
- #define APPEND_FILEMODE "a,recfm=vb,lrecl=259,blksize=6233"
- #define FTPTEMP_FILEMODE "w,recfm=vb,lrecl=23444,blksize=23448"
- #define FTPBIN_FILEMODE "wb,recfm=vb,lrecl=23444,blksize=23448"
- #define BKMGRBIN_FILEMODE "wb,recfm=fb,lrecl=4096,blksize=8192"
- #define SYSOUT_FILEMODE "w,recfm=vba,lrecl=133"
- #define OPEN_TEXT_FILE_FOR_WRITE(F) fopen((F),WRITE_FILEMODE)
- #define OPEN_TEXT_FILE_FOR_APPEND(F) fopen((F),APPEND_FILEMODE)
- #define OPEN_SYSOUT_FILE(F) fopen((F),SYSOUT_FILEMODE)
- #define OPEN_FTP_TEMP_FILE(F) fopen((F),FTPTEMP_FILEMODE)
- #define OPEN_FTP_BINARY_FILE(F) fopen((F),FTPBIN_FILEMODE)
- #define OPEN_BOOKMANAGER_BINARY_FILE(F) fopen((F),BKMGRBIN_FILEMODE)
- #define OPEN_TEXT_FILE_FOR_WRITE_OR_APPEND(F,B) \
- fopen((F),(B) ? APPEND_FILEMODE : WRITE_FILEMODE)
- #define OPEN_OUTPUT_FILE_FOR_WRITE_OR_APPEND(F,B) \
- fopen((F),(B) ? "a" : WRITE_FILEMODE)
- #define TEST_IF_FILE_EXISTS(P,F) (P=fopen((F),"r"))
- #define CLEANUP_IF_FILE_EXISTS(P) (void)fclose(P)
- #else
- #define WRITE_FILEMODE "w,recfm=v,reclen=255,blksize=6233"
- #define APPEND_FILEMODE "a,recfm=v,reclen=255,blksize=6233"
- #define FTPTEMP_FILEMODE "w,recfm=v,reclen=23444,blksize=23448"
- #define FTPBIN_FILEMODE "wb,recfm=v,reclen=23444,blksize=23448"
- #define SYSOUT_FILEMODE "w,recfm=v,reclen=133,print=yes"
- #define FILEMODE "recfm=v,reclen=255,blksize=6233"
- #define FILEMODE_A "recfm=v,reclen=133,print=yes"
- #define FILEMODE_T "recfm=v,reclen=512,blksize=23440"
- #define FILEMODE_BM "recfm=fb,reclen=4096,blksize=8192"
- #define OPEN_TEXT_FILE_FOR_WRITE(F) afopen((F),"w","seq",FILEMODE)
- #define OPEN_TEXT_FILE_FOR_APPEND(F) afopen((F),"a","seq",FILEMODE)
- #define OPEN_SYSOUT_FILE(F) afopen((F),"w","seq",FILEMODE_A)
- #define OPEN_FTP_TEMP_FILE(F) afopen((F),"w","seq",FILEMODE_T)
- #define OPEN_FTP_BINARY_FILE(F) afopen((F),"wb","seq",FILEMODE_T)
- #define OPEN_BOOKMANAGER_BINARY_FILE(F) \
- afopen((F),"wb","seq",FILEMODE_BM)
- #define OPEN_TEXT_FILE_FOR_WRITE_OR_APPEND(F,B) \
- afopen((F),(B)?"a":"w","seq",FILEMODE)
- #define OPEN_OUTPUT_FILE_FOR_WRITE_OR_APPEND(F,B) \
- afopen((F),(B)?"a":"w","seq",FILEMODE)
- #define TEST_IF_FILE_EXISTS(F,P) (access((F),0) == 0)
- #define CLEANUP_IF_FILE_EXISTS(P) /* */
- #endif
-
- #define uppercase_in_place(C) {char *__cp;\
- for(__cp=C;*__cp;__cp++) *__cp = toupper(*__cp);}
-
- #define lowercase_in_place(C) {char *__cp;\
- for(__cp=C;*__cp;__cp++) *__cp = tolower(*__cp);}
-
- #define strip_trailing_in_place(C) {char *__cp;\
- for(__cp=strchr((C),'\0');\
- __cp>C && isspace(*(__cp-1)); __cp--);\
- *__cp='\0';}
-
- #define strip_trailing_junk_in_place(C) {char *__cp;\
- for(__cp=strchr((C),'\0');\
- __cp>C && !isgraph(*(__cp-1)); __cp--);\
- *__cp='\0';}
-
- #define copy_uppercase(A,B) {char *__cA,*__cB;\
- for (__cA=A,__cB=B; *__cB;__cA++,__cB++)\
- *__cA = toupper(*__cB);\
- *__cA='\0';}
-
- #define copy_lowercase(A,B) {char *__cA,*__cB;\
- for (__cA=A,__cB=B; *__cB;__cA++,__cB++)\
- *__cA = tolower(*__cB);\
- *__cA='\0';}
-
- #define copy_uppercase(A,B) {char *__cA,*__cB;\
- for (__cA=A,__cB=B; *__cB;__cA++,__cB++)\
- *__cA = toupper(*__cB);\
- *__cA='\0';}
-
- #define copy_uppercase_and_strip_trailing(A,B,C) {char *__cA,*__cB;\
- for (__cA=A,__cB=B; *__cB;__cA++,__cB++)\
- *__cA = toupper(*__cB);\
- for (; __cA>A && isspace(*(__cA-1)); __cA--);\
- *__cA='\0';C=__cA;}
-
- #define copy_lowercase_and_strip_trailing(A,B,C) {char *__cA,*__cB;\
- for (__cA=A,__cB=B; *__cB;__cA++,__cB++)\
- *__cA = tolower(*__cB);\
- for (; __cA>A && isspace(*(__cA-1)); __cA--);\
- *__cA='\0';C=__cA;}
-
- #define skip_leading_space(C) (C) + strspn((C)," ")
- #define skip_whitespace(C) (C) + strspn((C)," \t")
- #define skip_ISPF_whitespace(C) (C) + strspn((C)," ,\t")
- #define find_whitespace(A,B) if (!(A=strpbrk((B)," \t")))\
- A = strchr((B),'\0');
- #define find_ISPF_whitespace(A,B) if (!(A=strpbrk((B)," ,\t")))\
- A = strchr((B),'\0');
-
- #define SPRINTF_IP_ADDRESS(A,B) sprintf((A),"%d.%d.%d.%d",\
- (*(((unsigned char *)(&(B)))+0)),\
- (*(((unsigned char *)(&(B)))+1)),\
- (*(((unsigned char *)(&(B)))+2)),\
- (*(((unsigned char *)(&(B)))+3)))
-
- /****** Data and structure definitions. ******************************/
-
- enum accreq {ACCESS_LOAD, ACCESS_CHECK, ACCESS_FREE};
- enum dstype {PDS, SEQ, UNK, JES};
- enum extreq {EXTRACT_IT, PRINT_IT, BOOKMARK_IT, BOOKMANAGE_IT};
- enum gohow {AS_NORMAL, AS_FILE, AS_NOTHING};
- enum iomode {NOCR, CRLF, RBIN};
- enum gostat {STATUS_OK, STATUS_EOF, STATUS_ERROR};
- enum option {OPTION_ALL, OPTION_VIEW, OPTION_OTHER};
- enum ostype {DEFAULT_OS, VM_OS};
- enum scroll {NO_SCROLL, UP, DOWN, LEFT, RIGHT, LOCATE};
- enum tmpfun {TEMP_CREATE, TEMP_CLOSE, TEMP_REMOVE};
- enum retval {
- SERVER_READ_OK,
- SERVER_READ_ERROR,
- SERVER_BUFFER_ERROR,
- SERVER_NO_MORE,
- SERVER_READ_NOTHING
- };
-
- typedef unsigned int IPADDRESS;
- typedef int SOCKETNO;
- typedef char GOPHERTYPE;
- typedef struct _textunit TEXTUNIT;
- typedef struct textline TEXTLINE;
- typedef struct texthdr TEXTHDR;
- typedef struct accessvector ACCESSVECTOR;
- typedef struct connection CONNECTION;
- typedef struct extraction EXTRACTION;
- typedef struct gopherinfo GOPHERINFO;
- typedef struct gopherplus GOPHERPLUS;
- typedef struct ggcb GGCB;
- typedef struct recvstruct RECV;
- typedef struct menuitem MENUITEM;
- typedef struct sysout SYSOUT;
- typedef struct tempfile TEMPFILE;
- typedef enum accreq ACCREQ;
- typedef enum dstype DSTYPE;
- typedef enum extreq EXTREQ;
- typedef enum gohow GOHOW;
- typedef enum gostat GOSTAT;
- typedef enum iomode IOMODE;
- typedef enum option OPTION;
- typedef enum ostype OSTYPE;
- typedef enum retval RETVAL;
- typedef enum scroll SCROLL;
- typedef enum tmpfun TMPFUN;
-
- #ifndef ACCESSRULE
- #define ACCESSRULE void
- #endif
-
- struct textline {
- struct textline *next;
- short text_length;
- short tab_expanded_text_length;
- char *tab_expanded_text;
- char text[1]; /* dummy */
- };
-
- struct texthdr {
- int text_line_count;
- TEXTLINE *text_body_line;
- short text_max_length;
- short text_max_tab_expanded_length;
- TEXTLINE *first_text_line;
- TEXTLINE *current_text_line;
- TEXTLINE *last_text_line;
- };
-
- struct _textunit {
- unsigned short key;
- unsigned short num;
- struct {
- unsigned short len;
- char prm[80];
- } ent;
- };
-
- struct sysout {
- int copies;
- char class [2];
- char dest [9];
- char userid [9];
- char forms [5];
- char ucs [5];
- };
-
- struct accessvector {
- int rulecount;
- int nextrule;
- ACCESSRULE *accessrule[1];
- };
-
- struct tempfile {
- FILE *fp;
- char ddname[12];
- char dsname[L_tmpnam];
- IOMODE crmode;
- };
-
- struct extraction {
- int from_number;
- int to_number;
- int count;
- DSTYPE mode;
- void (*closer)();
- Bool appending;
- Bool blanking;
- Bool tab_expanding;
- EXTREQ ex;
- char panelname [9];
- char dsname [65];
- char separator [81];
- char member_prefix [9];
- char ddname [9];
- char member [9];
- };
-
- struct gopherinfo {
- GOPHERTYPE type;
- int port;
- TEXTHDR thdr;
- char path [GOPHER_PATH_LENGTH+1];
- char host [GOPHER_HOST_LENGTH+1];
- char desc [GOPHER_DESC_LENGTH+1];
- char plus;
- char bmds [65]; /* bookmark file */
- };
-
- struct menuitem {
- char type; /* type of record to send */
- char desc [GOPHER_DESC_LENGTH+1];
- char select [GOPHER_PATH_LENGTH+1];
- char hostname [GOPHER_HOST_LENGTH+1];
- int port; /* host port to connect to */
- char gopherplus; /* null, '+' or '?' for ASK */
- };
-
- struct connection {
- char *server_buf;
- char *client_buf;
- int mybufl;
- int nbytes;
- int ibuflen;
- int bytes_returned;
- int buf_index;
- SOCKETNO ns;
- Bool time_to_go_home;
- Bool server_has_nothing;
- Bool server_finished_replying;
- Bool sending_text;
- Bool receiving_text;
- Bool dont_read;
- Bool connected_to_server;
- Bool connection_broken;
- Bool closing_connection;
- Bool is_ftp;
- char server_hostname [MAXHOSTNAMELEN+1];
- char buf [READ_BYTES];
- };
-
- struct Ftp {
- FILE *outfp;
- FILE *errfp;
- char *myname;
- struct hostent *server_hostent;
- struct hostent *client_hostent;
- int backlog;
- int myport;
- SOCKETNO listensocket;
- Bool verboseflag;
- Bool replaceflag;
- Bool listflag;
- Bool nlstflag;
- Bool binary;
- Bool control_socket_opened;
- Bool listen_socket_opened;
- Bool accept_socket_opened;
- GOPHERTYPE type;
- OSTYPE os;
- IPADDRESS hostaddress;
- CONNECTION control_connection;
- CONNECTION data_connection;
- struct sockaddr_in bindsock;
- struct sockaddr_in consock;
- char ftphack [16];
- char host [257];
- char user [257];
- char pass [257];
- char path [257];
- char client_hostname [257];
- char server_hostname [257];
- };
-
- struct gopherplus {
- int dummy; /* nothing yet */
- };
-
- struct recvstruct {
- int sockfd; /* socket descriptor for socket call */
- int outlen;
- int myport;
- int bytes_read;
- Bool binary;
- GOSTAT readstatus;
- FILE *outfp; /* used by local (non-socket) interface*/
- FILE *readfile; /* declare the file... */
- char *fileptr;
- char *wargptr;
- char *mytelnet;
- char *mybkmgr;
- char *mydomain;
- ACCESSVECTOR *accvector;
- GOPHERPLUS *gopherplus;
- TEMPFILE *temp;
- Bool (*openfun)();
- Bool (*readfun)();
- Bool (*closefun)();
- struct hostent clienthostent;
- char pathtype;
- char myname [MAXHOSTNAMELEN+1];
- char hostname[MAXHOSTNAMELEN+1]; /* client host name */
- char hosttest[MAXHOSTNAMELEN+1]; /* client host name */
- char buffer [RBUFSIZE]; /* client's character string */
- char dsname [RBUFSIZE];
- char sockbuf [OUTBUFSIZE]; /* socket output buffer */
- };
-
- struct ggcb {
- char *gopher_command;
- char *extract_separator_line;
- char *mytelnet;
- char *mybkmgr;
- char *mydomain;
- FILE *debug_file;
- FILE *extract_file;
- RECV *recvp;
- EXTRACTION *extractionp;
- GOPHERINFO *ginfo;
- #ifdef FETCH
- int (*isplink_pointer)();
- int (*ispexec_pointer)();
- #endif
- int ispfrc;
- int text_find_left_bound;
- int text_find_right_bound;
- int myport;
- Bool test_mode;
- Bool debug_mode;
- Bool quit;
- Bool local_mode;
- Bool extract_tab_expanding;
- Bool extract_appending;
- Bool extract_blank_before_separator;
- Bool extract_write_error;
- Bool extract_close_error;
- Bool warn_overwrite;
- Bool warn_append;
- Bool setmsg;
- Bool autoscroll;
- Bool autocursor;
- Bool setcursor;
- Bool printing;
- IPADDRESS client_ip_address;
- IPADDRESS server_ip_address;
- TEXTHDR thdr;
- CONNECTION gopher_connection;
- char client_ip_addrstr [16];
- char server_ip_addrstr [16];
- char ggserver [MAXHOSTNAMELEN+1];
- char ggclient [MAXHOSTNAMELEN+1];
- char client_hostname [MAXHOSTNAMELEN+1];
- char server_hostname [MAXHOSTNAMELEN+1];
- char text_find_string [81];
- char text_dispchar;
- char text_find_what;
- char text_find_type;
- char text_find_trans;
- char current_bookmark_ds [65];
- };
-
- #ifndef I370
- extern char ebcdictoascii[];
- extern char asciitoebcdic[];
- #endif
-
- #ifndef FETCH
- extern int isplink();
- extern int ispexec();
- #endif
-
- /****** Procedure and function declarations. *************************/
-
- extern Bool GGacces (RECV *, ACCREQ);
- extern DSTYPE GGalloc (char *, char *, DSTYPE, int);
- extern void GGbarf (RECV *, char *);
- extern Bool GGbin (GGCB *, GOPHERINFO *, GOHOW);
- extern Bool GGbkmgr (GGCB *, GOPHERINFO *, GOHOW);
- extern void GGclrtx (GGCB *, GOPHERINFO *);
- extern Bool GGconn (GGCB *, CONNECTION *);
- extern Bool GGcso (GGCB *, GOPHERINFO *, GOHOW);
- extern Bool GGdbm (GGCB *, GOPHERINFO *);
- extern void GGdfail (int, __S99parms *);
- extern Bool GGdir (GGCB *, GOPHERINFO *, GOHOW);
- extern void GGdisc (GGCB *, CONNECTION *);
- extern int GGdispl (GGCB *, char *);
- extern void GGdsopt (GGCB *, char *);
- extern void GGdump (GGCB *, char *, char *, int);
- extern void GGesrvr (GGCB *, CONNECTION *);
- extern void GGfreem (GGCB *, char *,char *);
- extern Bool GGftp (RECV *, struct Ftp *);
- extern FILE *GGgetds (GGCB *, EXTRACTION *);
- extern void GGgetm (GGCB *, char **,int,char *);
- extern Bool GGgofor (GGCB *, GOPHERINFO *, GOHOW);
- extern Bool GGgsrvl (GGCB *, CONNECTION *, char **, IOMODE);
- extern void GGierr (GGCB *);
- extern int GGiget (GGCB *, char *);
- extern Bool GGinfo (GGCB *, GOPHERINFO *);
- extern Bool GGispf (GGCB *, char *);
- extern Bool GGivget (GGCB *, char *, char *,int);
- extern Bool GGivput (GGCB *, char *, char *,int);
- extern Bool GGmenu (GGCB *, char *);
- extern void GGmtfer (int, char*);
- extern Bool GGouts (RECV *, char *, int);
- extern TEXTLINE *GGouttx (GGCB *, char *, GOPHERINFO *, int);
- extern Bool GGproc (RECV *, int);
- extern int GGrexx (RECV *, char *, char *);
- extern int GGsleep (int);
- extern Bool GGsockt (GGCB *, CONNECTION *);
- extern void GGsopt (GGCB *, OPTION);
- extern FILE *GGtemp (RECV *, TEMPFILE *, TMPFUN);
- extern Bool GGtnet (GGCB *, GOPHERINFO *, GOHOW);
- extern int GGtso (char *);
- extern char *GGtype (GOPHERTYPE);
- extern Bool GGunalc (char *);
- extern void GGview (GGCB *, GOPHERINFO *, TEXTHDR *, char *);
- extern Bool GGvtx (GGCB *, GOPHERINFO *, GOHOW);
- extern Bool GGwais (GGCB *, GOPHERINFO *, GOHOW);
- extern Bool GGwhois (GGCB *, GOPHERINFO *, GOHOW);
- extern int GGwto (char *);
- extern Bool GGxlist (GGCB *, char *);
- extern Bool GGxtx (GGCB *, GOPHERINFO *, EXTREQ);
-
- #ifndef SUPPRESS_V_DECLARATION
- extern void GGpmsg (GGCB *, int, char *, char *, ...);
- #endif
-
- /*********************************************************************/
-
- static char copyright_notice[] =
- "Copyright (c) The Charles Stark Draper Laboratory, 1992, 1993 \n\
- GOPHER server due to Shawn Hart at the University of Delaware. \n\
- GOPHER client due to Steve Bacher at Draper Laboratory. \n\
- SAS modifications due to Dale Ingold at SAS Institute, Inc. \n\
- \n\
- GOPHER server due to Shawn Hart at the University of Delaware. \n\
- \n\
- This software is provided on an 'AS IS' basis. All warranties, \n\
- including the implied warranties of merchantability and fitness,\n\
- are expressly denied. \n\
- \n\
- Provided this copyright notice is included, this software may \n\
- be freely distributed and not offered for sale. \n\
- \n\
- Changes or modifications may be made and used only by the maker \n\
- of same, and not further distributed. Such modifications should\n\
- be mailed to the author for consideration for addition to the \n\
- software and incorporation in subsequent releases.";
-
- /*********************************************************************/
-
- ./ ADD NAME=GGRX
-
- /********************************************************************/
- /* */
- /* Copyright (c) The Charles Stark Draper Laboratory, 1992, 1993 */
- /* GOPHER server due to Shawn Hart at the University of Delaware. */
- /* GOPHER client due to Steve Bacher at Draper Laboratory. */
- /* SAS modifications due to Dale Ingold at SAS Institute, Inc. */
- /* */
- /* This software is provided on an "AS IS" basis. All warranties, */
- /* including the implied warranties of merchantability and fitness, */
- /* are expressly denied. */
- /* */
- /* Provided this copyright notice is included, this software may */
- /* be freely distributed and not offered for sale. */
- /* */
- /* Changes or modifications may be made and used only by the maker */
- /* of same, and not further distributed. Such modifications should */
- /* be mailed to the author for consideration for addition to the */
- /* software and incorporation in subsequent releases. */
- /* */
- /********************************************************************/
-
- /* -------------------- "ggrx.h" include member -------------------- */
-
- #define PARAMETER unsigned int
- #define LASTPARM(X) ((unsigned int)(X) | 0x80000000)
-
- #define INVOKE_EXEC_AS_COMMAND (unsigned int)0x80000000
- #define INVOKE_EXEC_AS_EXTERNAL_FUNCTION (unsigned int)0x40000000
- #define INVOKE_EXEC_AS_SUBROUTINE (unsigned int)0x20000000
- #define RETURN_EXTENDED_RETURN_CODES (unsigned int)0x10000000
-
- /* the following take W as a work block extension address. */
-
- #define EXEC_INVOKED_AS_COMMAND(W) ((W)->flags && 0x7fffffff)
- #define EXEC_INVOKED_AS_EXTERNAL_FUNCTION(W) ((W)->flags && 0xbfffffff)
- #define EXEC_INVOKED_AS_SUBROUTINE(W) ((W)->flags && 0xdfffffff)
- #define EXEC_RETURNS_EXTENDED_RETURN_CODES(W) ((W)->flags && 0xefffffff)
-
- typedef int (*Rexxfun)();
-
- struct envblock {
- char id [8]; /* "ENVBLOCK" */
- char version [4]; /* "0200" */
- int length; /* 320 */
- struct parmblock *parmblock;
- void *userfield;
- struct workblockext *workblok_ext;
- void *irxexte;
- void *error_call_addr;
- void *reserved;
- char error_msgid [8];
- char primary_error_message [80];
- char alternate_error_message [160];
- /* The following fields are valid in TSO/E 2.3.1 (?) and higher. */
- void *compgmtb;
- void *attnrout_parmptr;
- };
-
- struct parmblock {
- char id [8]; /* "IRXPARMS" */
- char version [4]; /* "0200" */
- char language [3];
- char reserved [1];
- void *modnamet;
- void *subcomtb;
- void *packtb;
- char parsetok [8];
- unsigned int flags;
- unsigned int masks;
- int subpool;
- char *addrspn [8];
- char END [8]; /* 8X'FF' */
- };
-
- struct workblockext {
- struct execblock *execblk;
- void *argtable;
- unsigned int flags;
- struct instblock *instblk;
- struct cppl *cppl;
- struct evalblock *evalblock;
- char *workarea;
- void *userfield;
- /* The following fields are valid in TSO/E 2.3.1 (?) and higher. */
- void *rtproc;
- char *source_address;
- char *source_length;
- };
-
- struct instblock {
- int dummy;
- };
-
- struct evalblock {
- int dummy;
- };
-
- struct execblock {
- char acryn [8]; /* "IRXEXECB" */
- int length;
- int reserved1;
- char member [8];
- char ddname [8];
- char subcom [8];
- char *dsnptr;
- int dsnlen;
- };
-
- struct shvblock {
- struct shvblock *shvnext;
- int shvuser;
- char shvcode;
- char shvret;
- short reserved;
- int shvbufl;
- char *shvnama;
- int shvnaml;
- char *shvvala;
- int shvvall;
- };
-
- struct cppl {
- void *cpplcbuf;
- void *cpplupt;
- void *cpplpscb;
- void *cpplect;
- };
-
-
- /* --------------------- end of "ggrx.h" include ------------------- */
-
- ./ ADD NAME=GGSASC
-
- /********************************************************************/
- /* */
- /* Copyright (c) The Charles Stark Draper Laboratory, 1992, 1993 */
- /* GOPHER server due to Shawn Hart at the University of Delaware. */
- /* GOPHER client due to Steve Bacher at Draper Laboratory. */
- /* SAS modifications due to Dale Ingold at SAS Institute, Inc. */
- /* */
- /* This software is provided on an "AS IS" basis. All warranties, */
- /* including the implied warranties of merchantability and fitness, */
- /* are expressly denied. */
- /* */
- /* Provided this copyright notice is included, this software may */
- /* be freely distributed and not offered for sale. */
- /* */
- /* Changes or modifications may be made and used only by the maker */
- /* of same, and not further distributed. Such modifications should */
- /* be mailed to the author for consideration for addition to the */
- /* software and incorporation in subsequent releases. */
- /* */
- /********************************************************************/
-
- /* ------------------- "ggsasc.h" include member ------------------- */
-
- #ifdef SASC
-
- #define I370
-
- #include <dynam.h>
-
- #define FETCH
-
- /*
- * DEBUG is an automatic preprocessor symbol set by SAS/C if the DEBUG
- * option is specified.
- */
-
- #ifdef DEBUG
- #define ACTUAL_OR_INLINE __actual
- #else
- #define ACTUAL_OR_INLINE __inline
- #endif
-
- ACTUAL_OR_INLINE void (*fetch( const char *modname ))()
- {
- void (*fpp)();
-
- loadm( modname, &fpp );
- return( fpp );
- }
-
- ACTUAL_OR_INLINE int (*release( void (*fpp)() ))
- {
- unloadm( fpp );
- return( 0 );
- }
-
-
- #ifndef __SVC99
-
- #define __SVC99 1
-
- #include <code.h>
-
- struct __S99struc
- {
- unsigned char __S99RBLN; /* length of request block..20 */
- unsigned char __S99VERB; /* verb code */
- unsigned short __S99FLAG1; /* FLAGS1 field of SVC99 Req Block */
- unsigned short __S99ERROR; /* error code field */
- unsigned short __S99INFO; /* information reason code */
- void *__S99TXTPP; /* address of text unit pointer list*/
- int __reserved; /* reserved..will always be 0 */
- unsigned int __S99FLAG2; /* FLAGS2 field..can only be filled */
- /* in by APF authorized programs */
- };
-
- typedef struct __S99struc __S99parms;
-
- ACTUAL_OR_INLINE int svc99(__S99parms* svc99parmlist)
- { return( (_ldregs(R1, &svc99parmlist),
- _code(0, 0x9680, 0x1000),
- _code(0, 0x0a63),
- _stregs(R15) ) );
- }
-
- #endif
-
- #define FALSE 0
- #define TRUE 1
-
- #include <lcio.h>
-
- #define MAXHOSTNAMELEN 64
-
- #define __ctest(X) fprintf(stderr,\
- "GGMVS: CTEST is not supported by this compiler.")
-
- #endif
-
- ./ ADD NAME=GGSVC
-
- /********************************************************************/
- /* */
- /* Copyright (c) The Charles Stark Draper Laboratory, 1992, 1993 */
- /* GOPHER server due to Shawn Hart at the University of Delaware. */
- /* GOPHER client due to Steve Bacher at Draper Laboratory. */
- /* SAS modifications due to Dale Ingold at SAS Institute, Inc. */
- /* */
- /* This software is provided on an "AS IS" basis. All warranties, */
- /* including the implied warranties of merchantability and fitness, */
- /* are expressly denied. */
- /* */
- /* Provided this copyright notice is included, this software may */
- /* be freely distributed and not offered for sale. */
- /* */
- /* Changes or modifications may be made and used only by the maker */
- /* of same, and not further distributed. Such modifications should */
- /* be mailed to the author for consideration for addition to the */
- /* software and incorporation in subsequent releases. */
- /* */
- /********************************************************************/
-
- /* ------------------- "ggsvc.h" include member -------------------- */
-
- /*
- * Usage: SVC(SVC_NUMBER svcnumber,
- * SVC_REGISTER register15,
- * SVC_REGISTER register0,
- * SVC_REGISTER register1)
- *
- */
-
- #define SVC_NUMBER unsigned char
- #define SVC_REGISTER unsigned int
-
- #define SVC(_num,_r15,_r00,_r01) GGasvc((SVC_NUMBER) (_num),\
- (SVC_REGISTER *) (_r15),\
- (SVC_REGISTER *) (_r00),\
- (SVC_REGISTER *) (_r01))
- extern void GGasvc (SVC_NUMBER,
- SVC_REGISTER *,
- SVC_REGISTER *,
- SVC_REGISTER *);
-
- /* -------------------- end of "ggsvc.h" include ------------------- */
-
- ./ ADD NAME=GGSVC99
-
- /********************************************************************/
- /* */
- /* Copyright (c) The Charles Stark Draper Laboratory, 1992, 1993 */
- /* GOPHER server due to Shawn Hart at the University of Delaware. */
- /* GOPHER client due to Steve Bacher at Draper Laboratory. */
- /* SAS modifications due to Dale Ingold at SAS Institute, Inc. */
- /* */
- /* This software is provided on an "AS IS" basis. All warranties, */
- /* including the implied warranties of merchantability and fitness, */
- /* are expressly denied. */
- /* */
- /* Provided this copyright notice is included, this software may */
- /* be freely distributed and not offered for sale. */
- /* */
- /* Changes or modifications may be made and used only by the maker */
- /* of same, and not further distributed. Such modifications should */
- /* be mailed to the author for consideration for addition to the */
- /* software and incorporation in subsequent releases. */
- /* */
- /********************************************************************/
-
- /* ------------------ "ggsvc99.h" include member ------------------- */
-
- /********************************************************************/
- /* */
- /* The contents of this header are taken from the IBM assembler */
- /* macros IEFZB4D0 and IEFZB4D2, which are */
- /* (C) Copyright IBM Corp. 1981, 1990 */
- /* */
- /********************************************************************/
-
- #define S99VRBAL 0x01 /* ALLOCATION */
- #define S99VRBUN 0x02 /* UNALLOCATION */
- #define S99VRBCC 0x03 /* CONCATENATION */
- #define S99VRBDC 0x04 /* DECONCATENATION */
- #define S99VRBRI 0x05 /* REMOVE IN-USE */
- #define S99VRBDN 0x06 /* DDNAME ALLOCATION */
- #define S99VRBIN 0x07 /* INFORMATION RETRIEVAL */
- #define S99NOCNV 0x40 /* ALLOC FUNCTION-DO NOT USE AN */
- /* EXISTING ALLOCATION TO SATISFY*/
- /* THE REQUEST */
- #define DALDDNAM 0x0001 /* DDNAME */
- #define DALDSNAM 0x0002 /* DSNAME */
- #define DALMEMBR 0x0003 /* MEMBER NAME */
- #define DALSTATS 0x0004 /* DATA SET STATUS */
- #define DALNDISP 0x0005 /* DATA SET DISPOSITION */
- #define DALTRK 0x0007 /* TRACK SPACE TYPE */
- #define DALBLKLN 0x0009 /* BLOCK LENGTH */
- #define DALPRIME 0x000a /* PRIMARY SPACE ALLOCATION */
- #define DALSECND 0x000b /* SECONDARY SPACE ALLOCATION */
- #define DALDIR 0x000c /* DIRECTORY BLOCK ALLOCATION */
- #define DALSYSOU 0x0018 /* SYSOUT */
- #define DALSFMNO 0x001a /* SYSOUT FORMS NUMBER */
- #define DALCOPYS 0x001d /* SYSOUT COPIES */
- #define DALUCS 0x0029 /* UNIVERSAL CHARACTER SET */
- #define DALBLKSZ 0x0030 /* DCB BLOCKSIZE */
- #define DALDSORG 0x003c /* DATA SET ORGANIZATION */
- #define DALLRECL 0x0042 /* DCB LOGICAL RECORD LENGTH */
- #define DALRECFM 0x0049 /* DCB RECORD FORMAT */
- #define DALPERMA 0x0052 /* PERMANENTLY ALLOCATED ATTRIB */
- #define DALRTDDN 0x0055 /* RETURN DDNAME */
- #define DALRTDSN 0x0056 /* RETURN DSNAME */
- #define DALRTORG 0x0057 /* RETURN D.S. ORGANIZATION */
- #define DALSUSER 0x0058 /* SYSOUT REMOTE WORKSTATION */
- #define DALUSRID 0x0063 /* SYSOUT USER ID */
- #define DUNDDNAM 0x0001 /* DDNAME */
- #define DUNDSNAM 0x0002 /* DSNAME */
- #define DUNUNALC 0x0007 /* UNALLOC OPTION */
- #define SHR 0x08
- #define NEW 0x04
- #define MOD 0x02
- #define OLD 0x01
- #define KEEP 0x08
- #define DELETE 0x04
- #define CATLG 0x02
- #define UNCATLG 0x01
- #define RECFM_F 0x80
- #define RECFM_V 0x40
- #define RECFM_U 0xc0
- #define RECFM_D 0x20
- #define RECFM_T 0x20
- #define RECFM_B 0x10
- #define RECFM_S 0x08
- #define RECFM_A 0x04
- #define RECFM_M 0x02
- #define RECFM_FB (RECFM_F | RECFM_B)
- #define RECFM_VB (RECFM_V | RECFM_B)
- #define DSORG_PS 0x4000
- #define DSORG_PO 0x0200
-
- /* ------------------- end of "ggsvc99.h" include ------------------ */
-
- ./ ADD NAME=GGUSER
-
- /********************************************************************/
- /* */
- /* Copyright (c) The Charles Stark Draper Laboratory, 1992, 1993 */
- /* GOPHER server due to Shawn Hart at the University of Delaware. */
- /* GOPHER client due to Steve Bacher at Draper Laboratory. */
- /* SAS modifications due to Dale Ingold at SAS Institute, Inc. */
- /* */
- /* This software is provided on an "AS IS" basis. All warranties, */
- /* including the implied warranties of merchantability and fitness, */
- /* are expressly denied. */
- /* */
- /* Provided this copyright notice is included, this software may */
- /* be freely distributed and not offered for sale. */
- /* */
- /* Changes or modifications may be made and used only by the maker */
- /* of same, and not further distributed. Such modifications should */
- /* be mailed to the author for consideration for addition to the */
- /* software and incorporation in subsequent releases. */
- /* */
- /********************************************************************/
-
- /* ------------------- "gguser.h" include member ------------------- */
-
- /* Include file for locally customized values. */
-
- /* Define levels of C/370 and TCP/IP. This controls support for
- * fetching of non-C load modules and socket error reporting.
- */
-
- /* #define C370V1 /* define this if C/370 Version 1 */
- #define C370V2 /* define this if C/370 Version 2 or higher */
- /* #define SASC /* define this if SAS/C compiler */
-
- /* #define TCPIPV1 /* define this if TCP/IP Version 1 */
- #define TCPIPV2 /* define this if TCP/IP Version 2 or higher */
- /* #define SNSTCPIP /* define this if SNS/TCPAccess */
-
- /* #define ISPFV2 /* define this if ISPF Version 2 or earlier */
- #define ISPFV3 /* define this if ISPF Version 3 or later */
-
- /*
- * If you know about the IBM TCP/IP "CMXLATE" function, and you want
- * to use it, set the define accordingly.
- * SNS/TCP users should NOT set this define.
- */
-
- #define USE_CMXLATE
- /* #undef USE_CMXLATE */
-
- /*
- * Define this if you want DEST, FORMS and UCB for print requests.
- * Undefine it if you don't (you get just CLASS and COPIES).
- */
-
- #define FULLSYSOUT
- /* #undef FULLSYSOUT */
-
- /* Define the following defaults for your installation. */
- /* Use XTELNET if you like the CSOCK package from UCLA. */
-
- #define TELNET_COMMAND_NAME "TELNET"
- /* #define TELNET_COMMAND_NAME "XTELNET" */
-
- #define BOOKMGR_COMMAND_NAME "BOOKMGR"
-
- /* Define the following if you want to use the autologin */
- /* feature of XTELNET (i.e. XTELNET -l userid(/password) */
-
- /* #define XTELNET_AUTOLOGIN */
- #undef XTELNET_AUTOLOGIN
-
- /* Define this if the server host name set by the "+" frob
- * should have the domain name appended. Note that this will
- * affect how the hostname needs to be specified for a
- * Path=(pdsmember) specification - it must match the local host
- * the way it is generated here. Of course, host=+ will do it anyway.
- */
-
- #define APPEND_DOMAIN_NAME_TO_SELF
- /* #undef APPEND_DOMAIN_NAME_TO_SELF */
-
- /* Define the following if you want logging messages */
- /* sent as write-to-programmer messages to SYSLOG. */
-
- #define LOG_GOPHER_ACCESSES
- /* #undef LOG_GOPHER_ACCESSES */
-
- /*
- * Turn on for TCP-level debugging output (you probably don't want to
- * unless your TCP/IP stuff is really broken and I can't help you).
- */
-
- /* #define GOPHER_DEBUG */
- #undef GOPHER_DEBUG
-
- /*
- * Turn on for MTF-level debugging output.
- */
-
- /* #define DEBUGMTF */
- #undef DEBUGMTF
-
- /*
- * Turn on to debug the access table matching rules.
- */
-
- /* #define ACCESS_DEBUG */
- #undef ACCESS_DEBUG
-
- /* Server and MTF stuff. */
-
- /* #define MTF_TASKS 8 */
- #define MTF_TASKS 1 /* lest REXX multitasking lossage */
- #define TCP_QUEUE_LENGTH 20
- #define SERV_TCP_PORT 70
- #define CONNECT_TIME_OUT 60
- #define DEFAULT_DIRECTORY "DD:GGGOPHER"
- #define ACCESS_TABLE "DD:GGACCESS"
- #define DEBUG_FILE "DD:GGDEBUG"
- #define PARAMETER_FILE "DD:GGPARMS"
- #define MY_DOMAIN_SUFFIX ".DRAPER.COM"
- #define GOPHER_ADMIN "batchman@draper.com"
-
- /* note: could get MY_DOMAIN_SUFFIX from TCPIP startup - what call? */
-
- /* Client stuff. */
-
- #define INITIAL_TYPE GOPHER_DIRECTORY
- #define INITIAL_PORT GOPHER_PORT_NUMBER
- #define INITIAL_PATH ""
- #define INITIAL_HOST "MVS.DRAPER.COM"
- #define INITIAL_DESC "Root"
-
- /********************************************************************/
- /**** You probably should not modify anything below this point. ****/
- /********************************************************************/
-
- /* Server and client stuff. */
-
- #define IDENT_HOST_FROB "+"
- #define LOCAL_HOST_FROB "-"
-
- /********************************************************************/
- /* following are MVS file type identifiers. They must appear at the
- beginning of the file they're identifying. */
- /********************************************************************/
-
- #define MENUIDENT "GOPHER_MENU"
- #define INDEXIDENT "GOPHER_INDEX"
-
- /********************************************************************/
- /* following are tokens for menu GOPHER identifiers. */
- /********************************************************************/
-
- #define TOKTYPE "TYPE"
- #define TYPETOK 0
- #define TOKNAME "NAME"
- #define NAMETOK 1
- #define TOKPATH "PATH"
- #define PATHTOK 2
- #define TOKHOST "HOST"
- #define HOSTTOK 3
- #define TOKPORT "PORT"
- #define PORTTOK 4
- #define TOKEND "END"
- #define ENDTOK 5
- #define TOKCOMMENT1 '*'
- #define TOKCOMMENT2 '#'
- #define TOKCOMMENT3 '!'
- #define COMMENTTOK 6
- #define TOKDISPLAY "DISPLAY"
- #define DISPLAYTOK 7
- #define TOKSELECT "SELECTOR"
- #define SELECTTOK 8
- #define NULLTOK 9
-
- /********************************************************************/
- /* types of "types" - operands of the TYPE keyword in directories.*/
- /********************************************************************/
-
- #define TYPEFILE "FILE"
- #define TYPEMENU "DIRECTORY"
- #define TYPECSO "CSO"
- #define TYPEINDEX "INDEX"
- #define TYPETELNET "TELNET"
- #define TYPETN3270 "TN3270"
- #define TYPEBINARY "BINARY"
- #define TYPEWHOIS "WHOIS"
- #define TYPEBOOKMANAGER "BOOKMANAGER"
-
- /********************************************************************/
- /* used by the REXX Interface */
- /********************************************************************/
-
- /* Be sure to include all 8 bytes, including blanks, in below */
-
- #define REXX_EXEC_LIBRARY_DDNAME "GGEXEC "
- #define REXX_EXEC_SUBCOM " "
-
- ./ ENDUP
- ?!
- //C EXEC MDLOAD,BS='6160',TRK1='25',TRK2='1',TO='C'
- //SYSIN DD DATA,DLM='?!'
- ./ ADD NAME=GGACCES
-
- /********************************************************************/
- /* */
- /* Copyright (c) The Charles Stark Draper Laboratory, 1992, 1993 */
- /* GOPHER server due to Shawn Hart at the University of Delaware. */
- /* GOPHER client due to Steve Bacher at Draper Laboratory. */
- /* SAS modifications due to Dale Ingold at SAS Institute, Inc. */
- /* */
- /* This software is provided on an "AS IS" basis. All warranties, */
- /* including the implied warranties of merchantability and fitness, */
- /* are expressly denied. */
- /* */
- /* Provided this copyright notice is included, this software may */
- /* be freely distributed and not offered for sale. */
- /* */
- /* Changes or modifications may be made and used only by the maker */
- /* of same, and not further distributed. Such modifications should */
- /* be mailed to the author for consideration for addition to the */
- /* software and incorporation in subsequent releases. */
- /* */
- /********************************************************************/
-
- #pragma csect(code, "GG@ACCES")
- #pragma csect(static,"GG$ACCES")
-
- #define ACCESSRULE struct accessrule
-
- #include "gg.h"
-
- #define RULEPTRSIZE sizeof(ACCESSRULE *)
- #define ACCFILESIZE 63
-
- /*===================================================================*/
-
- struct accessrule {
- int number;
- int hostcount;
- int hosttextlen;
- int major_weight;
- int minor_weight;
- int part1len;
- int part2len;
- Bool wildcard;
- char accfile [ACCFILESIZE+1];
- char filepart1 [ACCFILESIZE+1];
- char filepart2 [ACCFILESIZE+1];
- char hosttext [1];
- };
-
- /*
- * There are three logical entry points:
- *
- * load_access_rules is called from the server main task.
- * check_access_rules is called from the server subtask.
- * free_access_rules is called from the server main task.
- *
- */
-
- /*===================================================================*/
-
- static GGCB dummy_ggcb;
-
- static GGCB *
- get_dummy_ggcb()
- {
- GGCB *gp;
-
- gp = &dummy_ggcb;
- CLEAR(gp);
-
- /* Uncomment the following to see GETMAIN and FREEMAIN debugging. */
- /* gp->debug_file = stderr; */
-
- return gp;
- }
-
- /*===================================================================*/
-
- static void
- ruledump(ACCESSRULE **rulep)
- {
- char *op;
- ACCESSRULE *rule = *rulep;
-
- fprintf(stderr,"Access rule at %8.8X\n\n",rulep);
- fprintf(stderr,"number........%d\n", rule->number);
- fprintf(stderr,"hostcount.....%d\n", rule->hostcount);
- fprintf(stderr,"hosttextlen...%d\n", rule->hosttextlen);
- fprintf(stderr,"major_weight..%d\n", rule->major_weight);
- fprintf(stderr,"minor_weight..%d\n", rule->minor_weight);
- fprintf(stderr,"part1len......%d\n", rule->part1len);
- fprintf(stderr,"part2len......%d\n", rule->part2len);
- fprintf(stderr,"wildcard......%d\n", rule->wildcard);
- fprintf(stderr,"accfile.......%s\n", rule->accfile);
- fprintf(stderr,"filepart1.....%s\n", rule->filepart1);
- fprintf(stderr,"filepart2.....%s\n", rule->filepart2);
- for (op = rule->hosttext; *op; op += strlen(op)+1) {
- fprintf(stderr,"host: %s\n", op);
- }
- fprintf(stderr,"\n");
- }
-
- /*===================================================================*/
-
- static ACCESSRULE **
- get_access_rule(RRECV *R,
- int textlen
- )
- {
- GGCB *gp = NULL;
- ACCESSVECTOR *oldav = NULL;
- ACCESSVECTOR *newav = NULL;
- ACCESSRULE **rulep = NULL;
- int howbig;
- int oldcount;
- int newcount;
- int oldnext;
-
- gp = get_dummy_ggcb();
-
- oldav = R->accvector;
- oldcount = oldav ? oldav->rulecount : 0;
- oldnext = oldav ? oldav->nextrule : 0;
-
- if (!oldav || oldav->nextrule >= oldav->rulecount) {
- newcount = oldcount + 100;
- howbig = sizeof(struct accessvector)+RULEPTRSIZE*newcount;
- GETMAIN(newav, char, howbig, "access rule vector");
- if (!newav) return NULL;
- if (oldav) {
- oldcount = oldav->rulecount;
- memcpy(newav->accessrule, oldav->accessrule, RULEPTRSIZE*oldcount);
- FREEMAIN(oldav,"old access rule vector");
- }
- newav->rulecount = newcount;
- newav->nextrule = oldnext;
- R->accvector = newav;
- }
- else {
- newav = oldav;
- }
- rulep = &newav->accessrule[newav->nextrule];
- newav->nextrule++;
- GETMAIN(*rulep,char,sizeof(ACCESSRULE)+textlen,"access rule");
- return rulep;
- }
-
- /*===================================================================*/
-
- /* Check for wildcarding and assign weights accordingly.
- *
- * Rule Weighting, Wildcarding and Prioritization
- *
- * Since with wildcards, a path can match more than
- * one rule, with possible conflicting results, we
- * establish an algorithm for picking the appropriate rule.
- *
- * Each rule is given a weight equal to the number of
- * explicit characters in the pathspec that matches the
- * target name. The rules with the highest weight will
- * be used - there may be more than one. Consider
- *
- * foo.bar.baz host0
- * foo.*.baz host1 host2 host3
- * foo.bar.* host4 hsot5 host6
- * foo.* host7 host8 host9
- * *.baz host10 host11 host12
- *
- * The above rules have weight 11, 8, 8, 4, 4 respectively.
- * For file foo.bar.baz, the first rule (with weight 11)
- * supersedes, obviously. For file foo.bar.mumble.baz,
- * all the rules except the first apply, so only the rules of
- * weight 8 (the maximum among the ones that match) will apply.
- * Now, to choose between the two rules, pick which one?
- *
- * Let's say the ones with the leftmost matching stuff
- * so that a minor weight equal to the length of the part
- * before the wildcard is used. (subweight of 11,4,8,4,0)
- *
- * (We could sort the rules as they are loaded; then
- * the first matching rule would apply)
- *
- * So for example:
- *
- * path major weight minor weight
- * foo.bar.baz 11 11
- * foo.bar.* 8 8
- * foo.*.baz 8 4
- * foo.* 4 4
- * *.baz 4 0
- *
- * would be in the above order.
- */
-
- static Bool
- weigh_rule(ACCESSRULE *rule)
- {
- Bool rc = FALSE;
- char *star;
- int filelen = strlen(rule->accfile);
-
- /* Set the weights for a non-wildcard path first. */
-
- star = strchr(rule->accfile,'*'); /* Locate wildcard character */
- if (!star) {
- rule->wildcard = FALSE;
- rule->major_weight = filelen;
- rule->minor_weight = filelen;
- return TRUE;
- }
-
- rule->wildcard = TRUE;
- rule->part1len = star - rule->accfile;
- rule->part2len = filelen - rule->part1len - 1;
- rule->major_weight = filelen - 1;
- rule->minor_weight = rule->part1len;
-
- strncpy(rule->filepart1, rule->accfile, rule->part1len);
- strncpy(rule->filepart2, star + 1, rule->part2len);
-
- if (strchr(rule->filepart2,'*')) {
- fprintf(stderr,"Multiple wildcard *'s not allowed: %s\n",
- rule->accfile);
- return FALSE;
- }
-
- return TRUE;
-
- }
-
- /*===================================================================*/
-
- static int
- compare_rule_weights(rule1,rule2)
- register const void *rule1;
- register const void *rule2;
- {
- register int major_weight_1 = (*(ACCESSRULE **)rule1)->major_weight;
- register int minor_weight_1 = (*(ACCESSRULE **)rule1)->minor_weight;
- register int major_weight_2 = (*(ACCESSRULE **)rule2)->major_weight;
- register int minor_weight_2 = (*(ACCESSRULE **)rule2)->minor_weight;
-
- /* This returns rules in descending order of major weight, and
- * in descending order of minor weight within that.
- */
-
- return (major_weight_2 == major_weight_1)
- ? (minor_weight_2 - minor_weight_1)
- : (major_weight_2 - major_weight_1);
-
- }
-
- /*===================================================================*/
-
- static void
- sort_rules(RRECV *R)
- {
- int rx;
- ACCESSRULE *rule;
-
- if (R->accvector) {
- qsort(R->accvector->accessrule,R->accvector->nextrule,RULEPTRSIZE,
- compare_rule_weights);
- for (rx = 0; rx < R->accvector->nextrule; rx++) {
- rule = R->accvector->accessrule[rx];
- rule->number = rx;
- }
- }
-
- }
-
- /*===================================================================*/
-
- static Bool
- load_access_rules(RRECV *R)
- {
- char *ip;
- char *op;
- char *rest_of_line;
- FILE *afp;
- ACCESSRULE *rule;
- ACCESSRULE **rulep;
- int rulenumber;
- int n;
- int hostcount;
- Bool rc;
- char accline [RBUFSIZE];
- char accfile [RBUFSIZE];
- char acchost [RBUFSIZE];
-
- /* If non-socket interface, bypass the authorization check. */
-
- if (R->outfp) return TRUE;
-
- /* Load rules from the access file. Each rule consists of a
- * pathname followed by a list of hostnames.
- * The pathname will be (dataset), EXEC:execname, or DD:file
- * - wildcards are also possible.
- */
-
- rc = TRUE;
- rulenumber = 0;
-
- afp = fopen(ACCESS_TABLE,"r");
- if (!afp) {
- perror(ACCESS_TABLE);
- fflush(stderr);
- return FALSE;
- }
-
- for (;;) {
- fgets(accline, sizeof(accline), afp);
- if (ferror(afp)) {
- fprintf(stderr,"Error reading access table %s\n",ACCESS_TABLE);
- rc = FALSE;
- break;
- }
- if (feof(afp)) break;
- uppercase_in_place(accline); /* format is: filename machine(s) */
- ip = accline; /* Start scan pointer */
- *accfile = '\0'; /* Clear access file name */
- sscanf(ip,"%s %n",accfile,&n); /* Get file name, bump scan */
- if (!*accfile) continue; /* Ignore blank lines */
- if (*accfile == '!' ) continue; /* Ignore comment lines */
- rulenumber++;
- if (strlen(accfile) > sizeof(rule->accfile)-1) {
- fprintf(stderr,"Access rule file name exceeds %d characters\n",
- sizeof(rule->accfile)-1);
- fprintf(stderr,"Cannot load rule: %s\n\n",accline);
- rc = FALSE;
- continue;
- }
- rest_of_line = ip + n;
- rulep = get_access_rule(R,strlen(rest_of_line));
- if (!rulep) break;
- rule = *rulep;
- if (!rule) break;
- CLEAR(rule);
- rule->number = rulenumber;
- rule->hosttextlen = strlen(rest_of_line);
- strncpy(rule->accfile, accfile, sizeof(rule->accfile));
-
- /* Loop over access host ids */
- for (ip = rest_of_line, op = rule->hosttext;;ip += n) {
- *acchost = '\0'; /* Clear word before scanf */
- sscanf(ip,"%s %n",acchost,&n); /* Get next word, bump scan */
- if (!*acchost) break; /* exit loop if no more hosts */
- strcpy(op,acchost);
- op += strlen(acchost) + 1;
- rule->hostcount++;
- }
-
- if (!weigh_rule(rule)) {
- fprintf(stderr,"Cannot load rule: %s\n\n",accline);
- rc = FALSE;
- continue;
- }
-
- }
-
- (void)fclose(afp);
-
- sort_rules(R);
-
- if (R->accvector) {
- int rx;
- for (rx = 0; rx < R->accvector->nextrule; rx++) {
- #ifdef ACCESS_DEBUG
- ruledump(&R->accvector->accessrule[rx]);
- #endif
- rule = R->accvector->accessrule[rx];
- fprintf(stderr,"Rule %d (%d,%d): %s\n",
- rule->number,rule->major_weight,rule->minor_weight,rule->accfile);
- }
- }
-
- fflush(stderr);
-
- return rc;
- }
-
- /*===================================================================*/
-
- static Bool
- free_access_rules(RRECV *R)
- {
- GGCB *gp = NULL;
- int i;
- if (!R->accvector) return TRUE;
-
- gp = get_dummy_ggcb();
-
- for (i = 0; i < R->accvector->nextrule; i++) {
- FREEMAIN(R->accvector->accessrule[i],"access rule");
- }
- FREEMAIN(R->accvector,"access rule vector");
-
- return TRUE;
- }
-
- /*===================================================================*/
-
- static Bool
- match(char *file,
- ACCESSRULE *rule)
- {
- int len;
-
- if (rule->wildcard) {
- len = strlen(file);
- return (rule->part1len <= len
- && rule->part2len <= len
- && !memcmp(file, rule->filepart1,rule->part1len)
- && !memcmp(file+len-rule->part2len,rule->filepart2,rule->part2len));
- }
- else return EQUAL(file,rule->accfile);
- }
-
- /*===================================================================*/
-
- static Bool
- check_access_rules(RRECV *R,
- char *fptr)
- {
- char *cp;
- char *hostp;
- ACCESSRULE *rule;
- int rx;
- int this_major_weight;
- int this_minor_weight;
- Bool rc;
- Bool matched;
- char filetest [RBUFSIZE];
-
- /* If non-socket interface, bypass the authorization check. */
-
- if (R->outfp) return TRUE;
-
- /* Check that the server is allowed to return data from the file
- * specified to this routine. Note that this could be the name of
- * an exec. The name will be (dataset), EXEC:execname, or DD:file
- * - we look at only the first part, whitespace-delimited.
- * Entries in the file authorization table look as above.
- */
-
- rc = FALSE;
- filetest[0] = '\0';
- sscanf(fptr,"%s",filetest);
-
- if (!R->accvector) {
- fprintf(stderr,"No rules, cannot authorize: %s\n",filetest);
- fflush(stderr);
- return FALSE;
- }
-
- /* The algorithm is this:
- *
- * The rules have already been sorted in descending weight order.
- * Try each rule until one that matches the file is found, whether
- * or not the hosts match. Save the major and minor weights of that
- * rule, because all rules with that set of weights will be tried to
- * look for a file-and-host match. So, proceed from that point,
- * trying each rule until one of the following occurs:
- *
- * - ran out of rules with same weights - fail
- * - found a file and a host that match - succeed
- *
- * Even if a non-match is found, we keep checking because
- * there may be more than one entry in the access table
- * for this file, so that more host names can be given.
- */
-
- for (rx = 0; rx < R->accvector->nextrule; rx++) {
- rule = R->accvector->accessrule[rx];
- if (match(filetest,rule)) {
- matched = TRUE;
- this_major_weight = rule->major_weight;
- this_minor_weight = rule->minor_weight;
- #ifdef ACCESS_DEBUG
- fprintf(stderr,"Rule %d (%d, %d): file name matches %s\n",
- rule->number,rule->major_weight,rule->minor_weight,
- rule->accfile);
- #endif
- for (;rx < R->accvector->nextrule; rx++) {
- rule = R->accvector->accessrule[rx];
- if (rule->major_weight != this_major_weight
- || rule->minor_weight != this_minor_weight) break;
- #ifdef ACCESS_DEBUG
- fprintf(stderr,"Trying rule %d (%d, %d): %s\n",
- rule->number,rule->major_weight, rule->minor_weight,
- rule->accfile);
- #endif
- if (!matched && !match(filetest,rule)) continue;
- matched = FALSE;
- if (!*rule->hosttext) {
- #ifdef ACCESS_DEBUG
- fprintf(stderr,"This rule matches for all host names\n");
- #endif
- rc = TRUE;
- break;
- }
- else {
- for (hostp=rule->hosttext; *hostp; hostp+=strlen(hostp)+1) {
- if (EQUAL(R->hostname,hostp)
- || EQUAL(R->hosttest,hostp)) { /* if hostname matches */
- #ifdef ACCESS_DEBUG
- fprintf(stderr,"This rule matches host name %s\n",hostp);
- #endif
- rc = TRUE;
- break;
- }
- }
- if (rc) break;
- }
- } /* end for */
- break; /* at end of this, we either got it or we don't */
- } /* end if match */
- } /* end for */
-
- if (!rc) {
- fprintf(stderr,"Not authorized from %s: '%s'\n",
- R->hosttest, filetest);
- }
-
- fflush(stderr);
-
- return rc;
- }
-
- /*===================================================================*/
-
- Bool
- GGacces(RRECV *R,
- ACCREQ req
- )
- {
-
- switch (req) {
- case ACCESS_LOAD: return load_access_rules(R);
- case ACCESS_CHECK: return check_access_rules(R,R->fileptr);
- case ACCESS_FREE: return free_access_rules(R);
- }
-
- }
-
- ./ ADD NAME=GGALLOC
-
- /********************************************************************/
- /* */
- /* Copyright (c) The Charles Stark Draper Laboratory, 1992, 1993 */
- /* GOPHER server due to Shawn Hart at the University of Delaware. */
- /* GOPHER client due to Steve Bacher at Draper Laboratory. */
- /* SAS modifications due to Dale Ingold at SAS Institute, Inc. */
- /* */
- /* This software is provided on an "AS IS" basis. All warranties, */
- /* including the implied warranties of merchantability and fitness, */
- /* are expressly denied. */
- /* */
- /* Provided this copyright notice is included, this software may */
- /* be freely distributed and not offered for sale. */
- /* */
- /* Changes or modifications may be made and used only by the maker */
- /* of same, and not further distributed. Such modifications should */
- /* be mailed to the author for consideration for addition to the */
- /* software and incorporation in subsequent releases. */
- /* */
- /********************************************************************/
-
- #pragma csect(code, "GG@ALLOC")
- #pragma csect(static,"GG$ALLOC")
- #include "gg.h"
- #include "ggsvc99.h"
-
- /****** Allocate a data set. *****************************************/
-
- DSTYPE
- GGalloc(dsname,ddname,wanted_type,nitems)
- char *dsname;
- char *ddname;
- DSTYPE wanted_type;
- int nitems;
- {
- int i;
- int rc;
- DSTYPE return_type;
- Bool try_new;
- short primary_allocation ;
- short secondary_allocation ;
- short directory_blocks ;
- short dsorg ;
- __S99parms stuff99; /* No "struct", despite manual */
- TEXTUNIT *tu [17];
- TEXTUNIT tu_dsn;
- TEXTUNIT tu_ddn;
- TEXTUNIT tu_member;
- TEXTUNIT tu_stat;
- TEXTUNIT tu_disp;
- TEXTUNIT tu_perm;
- TEXTUNIT tu_rtddn;
- TEXTUNIT tu_rtorg;
- TEXTUNIT tu_block;
- TEXTUNIT tu_prime;
- TEXTUNIT tu_sec;
- TEXTUNIT tu_dir;
- TEXTUNIT tu_recfm;
- TEXTUNIT tu_lrecl;
- TEXTUNIT tu_blksz;
- TEXTUNIT tu_dsorg;
- char *lparp;
- char *rparp;
- FILE *mfile;
- char dsnseq [81];
- char member [81];
- char what_to_open [81];
-
- try_new = FALSE;
-
- memset((char *)&stuff99,0,sizeof(__S99parms));
-
- strcpy(member,"");
- strcpy(dsnseq,dsname);
- lparp = strchr(dsnseq,'(');
- rparp = strchr(dsnseq,')');
- if (lparp && rparp && (lparp < rparp) && (*(rparp+1) == '\0')) {
- *lparp = '\0'; /* makes dsnseq the seq part only */
- *rparp = '\0'; /* turns member into a string */
- strcpy(member, lparp+1);
- wanted_type = PDS;
- }
-
- for (;;) {
-
- stuff99.__S99RBLN = 20;
- stuff99.__S99VERB = S99VRBAL;
- stuff99.__S99FLAG1 = S99NOCNV << 8;
- stuff99.__S99ERROR = 0;
- stuff99.__S99INFO = 0;
- stuff99.__S99TXTPP = tu;
- stuff99.__S99FLAG2 = 0;
-
- i = 0;
-
- tu[i++] = &tu_dsn;
-
- tu_dsn.key = DALDSNAM;
- tu_dsn.num = 1;
- tu_dsn.ent.len = strlen(dsnseq);
- copy_uppercase(tu_dsn.ent.prm,dsnseq);
-
- tu[i++] = &tu_stat;
-
- tu_stat.key = DALSTATS;
- tu_stat.num = 1;
- tu_stat.ent.len = 1;
- *tu_stat.ent.prm = (try_new ? NEW : SHR);
-
- tu[i++] = &tu_disp;
-
- tu_disp.key = DALNDISP;
- tu_disp.num = 1;
- tu_disp.ent.len = 1;
- *tu_disp.ent.prm = (try_new ? CATLG : KEEP);
-
- tu[i++] = &tu_rtorg;
-
- tu_rtorg.key = DALRTORG;
- tu_rtorg.num = 1;
- tu_rtorg.ent.len = 2;
-
- if (*member) {
-
- tu[i++] = &tu_member;
-
- tu_member.key = DALMEMBR;
- tu_member.num = 1;
- tu_member.ent.len = strlen(member);
- copy_uppercase(tu_member.ent.prm,member);
-
- }
-
- if (ddname && *ddname) {
-
- tu[i++] = &tu_ddn;
-
- tu_ddn.key = DALDDNAM;
- tu_ddn.num = 1;
- tu_ddn.ent.len = strlen(ddname);
- copy_uppercase(tu_ddn.ent.prm,ddname);
-
- tu[i++] = &tu_perm;
-
- tu_perm.key = DALPERMA;
- tu_perm.num = 0;
-
- }
- else {
-
- tu[i++] = &tu_rtddn;
-
- tu_rtddn.key = DALRTDDN;
- tu_rtddn.num = 1;
- tu_rtddn.ent.len = 8;
- memset(tu_rtddn.ent.prm,' ',8);
-
- }
-
- if (try_new) {
-
- switch (wanted_type) {
- case PDS:
- primary_allocation = (short)nitems;
- secondary_allocation = primary_allocation;
- directory_blocks = ((short)nitems/(12*36)+1) * 36;
- dsorg = DSORG_PO;
- break;
- case SEQ:
- default:
- primary_allocation = (short)nitems;
- secondary_allocation = primary_allocation;
- directory_blocks = 0;
- dsorg = DSORG_PS;
- break;
- }
-
- tu[i++] = &tu_block;
-
- tu_block.key = DALBLKLN;
- tu_block.num = 1;
- tu_block.ent.len = 3;
- memset(tu_block.ent.prm,0,3);
- *(short *)(tu_block.ent.prm+1) = 6233;
-
- tu[i++] = &tu_prime;
-
- tu_prime.key = DALPRIME;
- tu_prime.num = 1;
- tu_prime.ent.len = 3;
- memset(tu_prime.ent.prm,0,3);
- *(short *)(tu_prime.ent.prm+1) = primary_allocation;
-
- tu[i++] = &tu_sec;
-
- tu_sec.key = DALSECND;
- tu_sec.num = 1;
- tu_sec.ent.len = 3;
- memset(tu_sec.ent.prm,0,3);
- *(short *)(tu_sec.ent.prm+1) = secondary_allocation;
-
- tu[i++] = &tu_dir;
-
- tu_dir.key = DALDIR;
- tu_dir.num = 1;
- tu_dir.ent.len = 3;
- memset(tu_dir.ent.prm,0,3);
- *(short *)(tu_dir.ent.prm+1) = directory_blocks;
-
- tu[i++] = &tu_recfm;
-
- tu_recfm.key = DALRECFM;
- tu_recfm.num = 1;
- tu_recfm.ent.len = 1;
- *tu_recfm.ent.prm = RECFM_VB;
-
- tu[i++] = &tu_lrecl;
-
- tu_lrecl.key = DALLRECL;
- tu_lrecl.num = 1;
- tu_lrecl.ent.len = 2;
- *(short *)tu_lrecl.ent.prm = 259;
-
- tu[i++] = &tu_blksz;
-
- tu_blksz.key = DALBLKSZ;
- tu_blksz.num = 1;
- tu_blksz.ent.len = 2;
- *(short *)tu_blksz.ent.prm = 6233;
-
- tu[i++] = &tu_dsorg;
-
- tu_dsorg.key = DALDSORG;
- tu_dsorg.num = 1;
- tu_dsorg.ent.len = 2;
- *(short *)tu_dsorg.ent.prm = dsorg;
-
- }
-
- tu[i] = (void *)0x80000000;
-
- rc = svc99(&stuff99);
-
- if (rc == 0) {
- if (!(ddname && *ddname)) {
- memcpy(ddname,(char *)tu_rtddn.ent.prm,8);
- *(ddname+8) = ' ';
- *(strchr(ddname,' ')) = '\0';
- }
- switch (tu_rtorg.ent.prm[0]) {
- case 0x40: return_type = SEQ; break;
- case 0x02: return_type = PDS; break;
- default: return_type = UNK; break;
- }
- if (wanted_type == SEQ && return_type != SEQ) {
- fprintf(stderr,"%s: not a sequential data set\n",dsname);
- }
- if (wanted_type == PDS && return_type != PDS) {
- fprintf(stderr,"%s: not a partitioned data set\n",dsname);
- }
- if (return_type == PDS && *member) return SEQ;
- else return return_type;
- }
- else if (!try_new && nitems != 0 && stuff99.__S99ERROR == 0x1708) {
- try_new = TRUE;
- continue;
- }
- else {
- GGdfail(rc,&stuff99);
- return UNK;
- }
- }
- }
-
- ./ ADD NAME=GGASVC
-
- /********************************************************************/
- /* */
- /* Copyright (c) The Charles Stark Draper Laboratory, 1992, 1993 */
- /* */
- /* This software is provided on an "AS IS" basis. All warranties, */
- /* including the implied warranties of merchantability and fitness, */
- /* are expressly denied. */
- /* */
- /* Provided this copyright notice is included, this software may */
- /* be freely distributed and not offered for sale. */
- /* */
- /* Changes or modifications may be made and used only by the maker */
- /* of same, and not further distributed. Such modifications should */
- /* be mailed to the author for consideration for addition to the */
- /* software and incorporation in subsequent releases. */
- /* */
- /********************************************************************/
-
- #pragma csect(code, "GG@ASVC")
- #pragma csect(static,"GG$ASVC")
-
- #include "gg.h"
- #include "ggsvc.h"
-
- #define HEX(A) 0x##A
- #define I4(A,B,C,D) HEX(A), HEX(B), HEX(C), HEX(D)
- #define I2(A,B) HEX(A), HEX(B)
-
- /*
- * Usage: SVC(SVC_NUMBER svcnumber,
- * SVC_REGISTER register15,
- * SVC_REGISTER register0,
- * SVC_REGISTER register1)
- *
- * This routine invokes the specified SVC with the specified contents
- * of registers 15, 0 and 1, and fills in the returned values of those
- * registers on return from the SVC. That is why the caller must pass
- * the register words by reference.
- */
-
- void
- GGasvc(SVC_NUMBER num,
- SVC_REGISTER *r15,
- SVC_REGISTER *r00,
- SVC_REGISTER *r01
- )
- {
- void (*svccode)();
-
- static char assembler_code[] = {
- I4(90,ec,d0,0c), /* 0000 STM 14,12,12(13) */
- I2(18,3f), /* 0004 LR 3,15 */
- I4(98,47,10,00), /* 0006 LM 4,7,0(1) */
- I4(58,f0,50,00), /* 000A L 15,0(,5) */
- I4(58,00,60,00), /* 000E L 0,0(,6) */
- I4(58,10,70,00), /* 0012 L 1,0(,7) */
- I4(44,40,30,2c), /* 0016 EX 4,EXSVC */
- I4(50,f0,50,00), /* 001A ST 15,0(,5) */
- I4(50,00,60,00), /* 001E ST 0,0(,6) */
- I4(50,10,70,00), /* 0022 ST 1,0(,7) */
- I4(98,ec,d0,0c), /* 0026 LM 14,12,12(13) */
- I2(07,fe), /* 002A BR 14 */
- I2(0a,00) /* 002C EXSVC SVC 0 */
- };
-
- svccode = (void (*)()) assembler_code;
- (*svccode)(num,r15,r00,r01);
-
- return;
- }
-
- ./ ADD NAME=GGBARF
-
- /********************************************************************/
- /* */
- /* Copyright (c) The Charles Stark Draper Laboratory, 1992, 1993 */
- /* GOPHER server due to Shawn Hart at the University of Delaware. */
- /* GOPHER client due to Steve Bacher at Draper Laboratory. */
- /* SAS modifications due to Dale Ingold at SAS Institute, Inc. */
- /* */
- /* This software is provided on an "AS IS" basis. All warranties, */
- /* including the implied warranties of merchantability and fitness, */
- /* are expressly denied. */
- /* */
- /* Provided this copyright notice is included, this software may */
- /* be freely distributed and not offered for sale. */
- /* */
- /* Changes or modifications may be made and used only by the maker */
- /* of same, and not further distributed. Such modifications should */
- /* be mailed to the author for consideration for addition to the */
- /* software and incorporation in subsequent releases. */
- /* */
- /********************************************************************/
-
- #pragma csect(code, "GG@BARF")
- #pragma csect(static,"GG$BARF")
-
- #include "gg.h"
-
- void
- GGbarf(RECV *R,
- char *message)
- {
- char temp [257];
-
- if (!R->outfp) fprintf(stderr,"Barfing: %s\n", message);
-
- if (R->gopherplus) {
- if (!GGouts(R,"--1<" GOPHER_ADMIN ">", OUT_PLUS)) return;
- if (!GGouts(R,message, NO_VALUE)) return;
- }
- else {
- /* the number should be 3 (ERROR) but some clients may not show it
- * |
- * V
- */
- sprintf(temp, "1%s.\t0\t0\t0", message);
- (void)GGouts(R,temp,NO_VALUE);
- }
- return;
- }
-
- ./ ADD NAME=GGBIN
-
- /********************************************************************/
- /* */
- /* Copyright (c) The Charles Stark Draper Laboratory, 1992, 1993 */
- /* GOPHER server due to Shawn Hart at the University of Delaware. */
- /* GOPHER client due to Steve Bacher at Draper Laboratory. */
- /* SAS modifications due to Dale Ingold at SAS Institute, Inc. */
- /* */
- /* This software is provided on an "AS IS" basis. All warranties, */
- /* including the implied warranties of merchantability and fitness, */
- /* are expressly denied. */
- /* */
- /* Provided this copyright notice is included, this software may */
- /* be freely distributed and not offered for sale. */
- /* */
- /* Changes or modifications may be made and used only by the maker */
- /* of same, and not further distributed. Such modifications should */
- /* be mailed to the author for consideration for addition to the */
- /* software and incorporation in subsequent releases. */
- /* */
- /********************************************************************/
-
- #pragma csect(code, "GG@BIN ")
- #pragma csect(static,"GG$BIN ")
- #include "gg.h"
-
- /****** Display a binary file retrieved from the server. *************/
-
- Bool
- GGbin(gp,ip,how)
- RGGCB *gp;
- RINFO *ip;
- GOHOW how;
- {
- TEXTHDR *texthdrp;
- char title [81];
-
- switch (how) {
- case AS_NOTHING: return;
- default: break;
- }
-
- texthdrp = (ip ? &ip->thdr : &gp->thdr);
-
- if (!ip) sprintf(title, "GopherServer:%s ",gp->ggserver);
- else strncpy(title, ip->desc, sizeof(title));
-
- GGview(gp,ip,texthdrp,title);
-
- return;
- }
-
- ./ ADD NAME=GGBKMGR
-
- /********************************************************************/
- /* */
- /* Copyright (c) The Charles Stark Draper Laboratory, 1992, 1993 */
- /* GOPHER server due to Shawn Hart at the University of Delaware. */
- /* GOPHER client due to Steve Bacher at Draper Laboratory. */
- /* SAS modifications due to Dale Ingold at SAS Institute, Inc. */
- /* */
- /* This software is provided on an "AS IS" basis. All warranties, */
- /* including the implied warranties of merchantability and fitness, */
- /* are expressly denied. */
- /* */
- /* Provided this copyright notice is included, this software may */
- /* be freely distributed and not offered for sale. */
- /* */
- /* Changes or modifications may be made and used only by the maker */
- /* of same, and not further distributed. Such modifications should */
- /* be mailed to the author for consideration for addition to the */
- /* software and incorporation in subsequent releases. */
- /* */
- /********************************************************************/
-
- #pragma csect(code, "GG@BKMGR")
- #pragma csect(static,"GG$BKMGR")
- #include "gg.h"
-
- /****** Display a BookManager (C) IBM file from the server. **********/
-
- Bool
- GGbkmgr(gp,ip,how)
- RGGCB *gp;
- RINFO *ip;
- GOHOW how;
- {
- int tsorc;
- Bool ok = FALSE;
- FILE *tempfile = NULL;
- char ddname [ 12];
- char tempdsn [257];
- char command [257];
-
- switch (how) {
- case AS_NOTHING: return;
- default: break;
- }
-
- /* Create temporary file to hold binary BookManager data. */
-
- if (!tmpnam(tempdsn)) {
- ERR1("Could not create temporary file for BookManager");
- return FALSE;
- }
-
- strcpy(ddname,"dd:");
-
- if (GGalloc(tempdsn,ddname+3,SEQ,500) != SEQ) {
- ERR2("The temporary file %s could not be allocated.",
- tempdsn);
- return FALSE;
- }
-
- tempfile = OPEN_BOOKMANAGER_BINARY_FILE(ddname);
- if (!tempfile) {
- perror(tempdsn);
- ERR2("The temporary file %s could not be opened.", tempdsn);
- return FALSE;
- }
-
- /* Write binary text data to temporary file. */
-
- ok = TRUE;
-
- if (ip->thdr.first_text_line) {
- gp->extract_file = tempfile;
- if (!GGxtx(gp,ip,BOOKMANAGE_IT)) {
- ERR2("Error writing to temporary BookManager file %s",tempdsn);
- ok = FALSE;
- }
- }
- else {
- ERR1("The retrieved BookManager file is empty.");
- ok = FALSE;
- }
-
- if (fclose(tempfile) < 0) {
- ERR2("The temporary BookManager file %s could not be closed.",
- tempdsn);
- return FALSE;
- }
-
- (void)GGunalc(ddname+3);
-
- if (ok) {
-
- sprintf(command,"%s BOOK(%s)",gp->mybkmgr,tempdsn);
-
- if ((tsorc = GGtso(command)) != 0) {
- ERR3("Command \"%s\" returned code %d", command, tsorc);
- }
-
- /* Remove temporary file. */
-
- if (remove(tempdsn) < 0) {
- ERR2("The temporary BookManager file %s could not be removed.",
- tempdsn);
- }
-
- }
-
- ISPF("CONTROL DISPLAY REFRESH");
-
- return ok;
- }
-
- ./ ADD NAME=GGCLIEN
-
- /********************************************************************/
- /* */
- /* Copyright (c) The Charles Stark Draper Laboratory, 1992, 1993 */
- /* GOPHER server due to Shawn Hart at the University of Delaware. */
- /* GOPHER client due to Steve Bacher at Draper Laboratory. */
- /* SAS modifications due to Dale Ingold at SAS Institute, Inc. */
- /* */
- /* This software is provided on an "AS IS" basis. All warranties, */
- /* including the implied warranties of merchantability and fitness, */
- /* are expressly denied. */
- /* */
- /* Provided this copyright notice is included, this software may */
- /* be freely distributed and not offered for sale. */
- /* */
- /* Changes or modifications may be made and used only by the maker */
- /* of same, and not further distributed. Such modifications should */
- /* be mailed to the author for consideration for addition to the */
- /* software and incorporation in subsequent releases. */
- /* */
- /********************************************************************/
-
- #ifdef SASC
- #pragma runopts(EXECOPS)
- #else
- #pragma runopts(heap(8k,8k,anywhere,))
- #endif
-
- #pragma csect(code, "GG@CLIEN")
- #pragma csect(static,"GG$CLIEN")
- #include "gg.h"
-
- #ifdef I370
- char * _style = "tso:";
- #endif
-
- /*********************************************************************/
-
- static void
- trap_ispf_command(gp,verb,action)
- RGGCB *gp;
- char *verb;
- char *action;
- {
- char zcttrunc [16];
- char zctact [64];
- char zctdesc [128];
-
- if (!VPUT("ZCTVERB ",verb)) return;
-
- if (!ISPF("TBTOP ISPCMDS")) return;
- if (!ISPF("TBSCAN ISPCMDS ARGLIST(ZCTVERB)")) return;
- if (!VGET("ZCTACT ",zctact)) return;
- if (UNEQUAL(zctact,action)) {
- VGET("ZCTTRUNC ",zcttrunc);
- VGET("ZCTDESC ",zctdesc );
- if (!ISPF("TBTOP ISPCMDS")) return;
- VPUT("ZCTACT ",action );
- VPUT("ZCTTRUNC ",zcttrunc);
- VPUT("ZCTDESC ",zctdesc );
- if (!ISPF("TBADD ISPCMDS")) return;
- }
-
- return;
- }
-
- /*********************************************************************/
-
- static Bool
- go_for_it(gp,ip)
- RGGCB *gp;
- RINFO *ip;
- {
-
- VGET("GGHOST ",ip->host);
- VGET("GGPATH ",ip->path);
- VGET("GGDESC ",ip->desc);
- ip->port = IGET("GGPORT ");
- ip->type = INITIAL_TYPE;
- if (!*ip->path) strcpy(ip->path,INITIAL_PATH);
- if (!*ip->host) strcpy(ip->host,INITIAL_HOST);
- if (!*ip->desc) strcpy(ip->desc,INITIAL_DESC);
- if (ip->port == 0) ip->port = INITIAL_PORT;
- *ip->bmds = '\0';
- return GGgofor(gp,ip,AS_NORMAL);
-
- }
-
- /*********************************************************************/
-
- int
- main(argc,argv)
- int argc;
- char **argv;
- {
- GGCB *gp;
- GOPHERINFO *ip;
- CONNECTION *sp;
- char *p;
- int i;
- int exitrc;
- Bool bypass_startup;
- GGCB gg;
- char ggdomain [129];
- char ggtelnet [129];
- char ggbkmgr [129];
- char zerrsm [25];
- char zerrlm [ZERRLM_SIZE];
-
- exitrc = 0;
- gp = ≫
- CLEAR(gp);
-
- GETMAIN(ip, GOPHERINFO, 1, "top-level gopherinfo struct");
- if (!ip) {
- fprintf(stderr,"Not enough memory to start up GOPHER\n");
- exit(16);
- }
-
- CLEAR(ip);
- gp->ginfo = ip;
-
- for (i = 1; i < argc; i++) {
- p = argv[i];
- if (*p == '-') {
- while (*++p) {
- switch (toupper(*p)) {
- case 'T': gp->test_mode = TRUE; break;
- case 'D': gp->debug_mode = TRUE; break;
- case 'L': gp->local_mode = TRUE; break;
- case 'Q': bypass_startup = TRUE; break;
- default: fprintf(stderr,"GGMVS: Bad parameter flag %c\n",*p);
- exitrc = 8;
- }
- }
- }
- else {
- fprintf(stderr,"GGMVS: Bad parameter string %s\n",p);
- exitrc = 8;
- }
- }
-
- if (gp->test_mode) __ctest(NULL);
-
- if (gp->debug_mode) {
- if (!(gp->debug_file = fopen(DEBUG_FILE,"w"))) {
- perror(DEBUG_FILE);
- exitrc = 4;
- }
- }
-
- GGclrtx(gp,NULL); /* Clear text */
- GGclrtx(gp,ip); /* Clear text */
-
- /* These may be overridden from gopherrc. */
-
- gp->myport = SERV_TCP_PORT;
- gp->mytelnet = TELNET_COMMAND_NAME;
- gp->mybkmgr = BOOKMGR_COMMAND_NAME;
- gp->mydomain = MY_DOMAIN_SUFFIX;
-
- sp = &gp->gopher_connection;
-
- GETMAIN(sp->server_buf, char,SERVER_BUF_MSGSIZE+4,"server buffer");
- GETMAIN(sp->client_buf, char,CLIENT_BUF_MSGSIZE+4,"client buffer");
- GETMAIN(gp->gopher_command,char,CLIENT_BUF_MSGSIZE+4,"gopher command");
-
- #ifdef FETCH
- gp->isplink_pointer = (int (*) ())fetch("ISPLINK");
- gp->ispexec_pointer = (int (*) ())fetch("ISPEXEC");
- #endif
-
- if (!ISPF("CONTROL ERRORS RETURN")) exitrc = 20;
-
- else {
-
- exitrc = 0;
- trap_ispf_command(gp,"RFIND","&YRFIND"); /* enable RFIND */
-
- ISPF("TBGET GOPHERVT"); /* get Gopher startup variables */
- ISPF("TBCLOSE GOPHERVT"); /* ... in case of split screen gophers */
-
- VGET("GGDOMAIN ",ggdomain);
- VGET("GGTELNET ",ggtelnet);
- VGET("GGBKMGR ",ggbkmgr );
- if (*ggdomain) gp->mydomain = ggdomain;
- if (*ggtelnet) gp->mytelnet = ggtelnet;
- if (*ggbkmgr) gp->mybkmgr = ggbkmgr;
-
- GGsopt(gp,OPTION_ALL); /* set options */
-
- if (bypass_startup) { /* use values put in table by exec */
- (void)go_for_it(gp,ip);
- }
- else {
- VPUT("ZCMD ","");
- while (GGdispl(gp,"GGM ") == 0
- && !gp->quit
- && !go_for_it(gp,ip)) ;
- }
- }
-
- if (gp->setmsg) {
- VGET("ZERRSM ",zerrsm);
- VGET("ZERRLM ",zerrlm);
- fprintf(stderr,"%s: %s\n",zerrsm,zerrlm);
- gp->setmsg = FALSE;
- }
-
- if (sp->connected_to_server) {
- GGdisc(gp,sp); /* disconnect from gopher server */
- }
-
- FREEMAIN(gp->gopher_command,"gopher command");
- FREEMAIN(sp->server_buf, "server buffer");
- FREEMAIN(sp->client_buf, "client buffer");
- FREEMAIN(ip, "top-level gopherinfo struct");
-
- #define FINAL_CLOSE(A,B) \
- if (A) { \
- if (fclose(A) < 0) fprintf(stderr,B); \
- }
-
- FINAL_CLOSE(gp->debug_file, "Error closing debug file\n");
-
- exit(exitrc);
- }
-
- ./ ADD NAME=GGCLRTX
-
- /********************************************************************/
- /* */
- /* Copyright (c) The Charles Stark Draper Laboratory, 1992, 1993 */
- /* GOPHER server due to Shawn Hart at the University of Delaware. */
- /* GOPHER client due to Steve Bacher at Draper Laboratory. */
- /* SAS modifications due to Dale Ingold at SAS Institute, Inc. */
- /* */
- /* This software is provided on an "AS IS" basis. All warranties, */
- /* including the implied warranties of merchantability and fitness, */
- /* are expressly denied. */
- /* */
- /* Provided this copyright notice is included, this software may */
- /* be freely distributed and not offered for sale. */
- /* */
- /* Changes or modifications may be made and used only by the maker */
- /* of same, and not further distributed. Such modifications should */
- /* be mailed to the author for consideration for addition to the */
- /* software and incorporation in subsequent releases. */
- /* */
- /********************************************************************/
-
- #pragma csect(code, "GG@CLRTX")
- #pragma csect(static,"GG$CLRTX")
- #include "gg.h"
-
- /****** Clear text. **************************************************/
-
- void
- GGclrtx(gp,ip)
- RGGCB *gp;
- RINFO *ip;
- {
- register TEXTHDR *thp;
- register TEXTLINE *tp1;
- register TEXTLINE *tp2;
-
- /* If info is not specified, use main ggcb, else info's text */
-
- thp = (ip ? &ip->thdr : &gp->thdr);
-
- tp1 = thp->first_text_line;
- while (tp1) {
- tp2 = tp1->next;
- FREEMAIN(tp1,"text line");
- tp1 = tp2;
- }
-
- CLEAR(thp);
-
- return;
-
- }
-
- ./ ADD NAME=GGCONN
-
- /********************************************************************/
- /* */
- /* Copyright (c) The Charles Stark Draper Laboratory, 1992, 1993 */
- /* GOPHER server due to Shawn Hart at the University of Delaware. */
- /* GOPHER client due to Steve Bacher at Draper Laboratory. */
- /* SAS modifications due to Dale Ingold at SAS Institute, Inc. */
- /* */
- /* This software is provided on an "AS IS" basis. All warranties, */
- /* including the implied warranties of merchantability and fitness, */
- /* are expressly denied. */
- /* */
- /* Provided this copyright notice is included, this software may */
- /* be freely distributed and not offered for sale. */
- /* */
- /* Changes or modifications may be made and used only by the maker */
- /* of same, and not further distributed. Such modifications should */
- /* be mailed to the author for consideration for addition to the */
- /* software and incorporation in subsequent releases. */
- /* */
- /********************************************************************/
-
- #pragma csect(code, "GG@CONN ")
- #pragma csect(static,"GG$CONN ")
- #include "gg.h"
-
- /****** Get client hostname and IP address. **************************/
-
- static Bool
- get_client_hostname(gp)
- RGGCB *gp;
- {
- struct hostent *client_hp;
- int gethostnamerc;
- int hostlen;
- int domslen;
-
- gethostnamerc = gethostname(gp->client_hostname,MAXHOSTNAMELEN);
- if (gethostnamerc < 0) {
- fprintf(stderr,"GGMVS: gethostname() failed, don't know my name\n");
- return FALSE;
- }
-
- #ifdef APPEND_DOMAIN_NAME_TO_SELF
-
- hostlen = strlen(gp->client_hostname);
- domslen = strlen(gp->mydomain);
- if (hostlen <= domslen ||
- memcmp(gp->client_hostname+hostlen-domslen,gp->mydomain,domslen)) {
- strncat(gp->client_hostname,gp->mydomain,domslen);
- }
-
- #endif
-
- uppercase_in_place(gp->client_hostname);
-
- client_hp = gethostbyname(gp->client_hostname);
- if (!client_hp) {
- fprintf(stderr,
- "GGMVS: gethostbyname(%s) failed, can't get my name\n",
- gp->client_hostname);
- return FALSE;
- }
-
- strcpy(gp->ggclient,gp->client_hostname);
- strcpy(gp->client_hostname, client_hp->h_name);
- gp->client_ip_address = *(IPADDRESS *)client_hp->h_addr;
-
- return TRUE;
-
- }
-
- /****** Connect to news server. **************************************/
-
- Bool
- GGconn(gp,sp)
- RGGCB *gp;
- RCONN *sp;
- {
- char *lp;
- char *cp;
- RECV *R;
- struct hostent *server_hp;
- struct sockaddr_in bindsock;
- struct sockaddr_in consock;
- int bindrc;
- int connrc;
- int ip_part_1;
- int ip_part_2;
- int ip_part_3;
- int ip_part_4;
- char tempdsn [L_tmpnam];
-
- if (sp->connected_to_server) {
- GGdisc(gp,sp); /* Disconnect from gopher server */
- }
-
- sp->closing_connection = FALSE;
- sp->buf_index = -1;
- sp->bytes_returned = 0;
- sp->receiving_text = FALSE;
- sp->is_ftp = FALSE;
-
- if (!*gp->ggserver) {
- ERR1(
- "No host server defined in Gopher menu. Cannot make a connection.");
- return FALSE;
- }
-
- uppercase_in_place(gp->ggserver);
-
- /* If server is "local hack", then establish local mode,
- * open temporary file and return.
- */
-
- if (!strcmp(gp->ggserver, LOCAL_HOST_FROB)) {
-
- if (gp->ginfo->port != GOPHER_PORT_NUMBER) {
- ERR3("Server name %s is permitted only with port number %d.",
- LOCAL_HOST_FROB, GOPHER_PORT_NUMBER);
- return FALSE;
- }
-
- GETMAIN(gp->recvp, RECV, 1, "local recv struct");
- if (!gp->recvp) {
- CRIT1("Can't get memory for local host struct");
- return FALSE;
- }
- R = gp->recvp;
- CLEAR(R);
-
- R->myport = gp->myport;
- R->mytelnet = gp->mytelnet;
- R->mybkmgr = gp->mybkmgr;
- R->mydomain = gp->mydomain;
-
- if (!tmpnam(tempdsn)) {
- CRIT1("Can't create temporary file for local access");
- return FALSE;
- }
-
- /* Create temporary file for writing and reading. */
-
- R->outfp = fopen(tempdsn,"w+,type=memory");
- if (!R->outfp) {
- perror(tempdsn);
- CRIT1("Can't open temporary file for local access");
- return FALSE;
- }
-
- sp->connected_to_server = TRUE;
- sp->time_to_go_home = FALSE;
- sp->connection_broken = FALSE;
-
- GGesrvr(gp,sp); /* Clean up any stray responses from server. */
-
- return TRUE;
- }
-
- /* Disallow network connections if started up in local mode. */
-
- if (gp->local_mode) {
- ERR1("Network connections are not allowed in local mode.");
- return FALSE;
- }
-
- /* Determine the local path name. Do only if making net conn. */
-
- if (!*gp->client_hostname) {
- if (!get_client_hostname(gp)) return FALSE;
- }
-
- /* Get server name and address. */
-
- if (strchr(gp->ggserver,'.') &&
- gp->ggserver[strspn(gp->ggserver,".0123456789")] == '\0') {
- ip_part_1 = ip_part_2 = ip_part_3 = ip_part_4 = 32767;
- strcpy(gp->server_hostname, gp->ggserver);
- strcpy(sp->server_hostname, gp->ggserver);
- sscanf(gp->ggserver,"%d.%d.%d.%d",
- &ip_part_1,&ip_part_2,&ip_part_3,&ip_part_4);
- if (ip_part_1 > 255 ||
- ip_part_2 > 255 ||
- ip_part_3 > 255 ||
- ip_part_4 > 255) {
- ERR2("Syntax error in server network address: %s", gp->ggserver);
- return FALSE;
- }
- gp->server_ip_address = (IPADDRESS) ((ip_part_1 << 24) +
- (ip_part_2 << 16) +
- (ip_part_3 << 8) +
- (ip_part_4 ));
- }
- else {
- server_hp = gethostbyname(gp->ggserver);
- if (!server_hp) {
- ERR2(
- "Unknown host %s - gethostbyname() could not resolve the server name.",
- gp->ggserver);
- return FALSE;
- }
- strcpy(gp->server_hostname, server_hp->h_name);
- strcpy(sp->server_hostname, server_hp->h_name);
- gp->server_ip_address = *(IPADDRESS *)server_hp->h_addr;
- }
-
- SPRINTF_IP_ADDRESS(gp->server_ip_addrstr, gp->server_ip_address);
- SPRINTF_IP_ADDRESS(gp->client_ip_addrstr, gp->client_ip_address);
-
- VPUT("GGSERVER ",gp->ggserver);
- VPUT("GGCLIENT ",gp->ggclient);
- VPUT("GGSERVIP ",gp->server_ip_addrstr);
- VPUT("GGCLIEIP ",gp->client_ip_addrstr);
-
- consock.sin_family = AF_INET;
- consock.sin_port = htons(gp->ginfo->port);
- consock.sin_addr.s_addr = gp->server_ip_address;
-
- bindsock.sin_family = AF_INET;
- bindsock.sin_port = 0;
- bindsock.sin_addr.s_addr = INADDR_ANY;
-
- sp->ns = socket(AF_INET, SOCK_STREAM, 0);
- if (sp->ns < 0) {
- REPORT_TCP_ERROR(gp->ggserver);
- ERR2("TCP/IP error: socket() failed to make socket for server %s.",
- gp->ggserver);
- return FALSE;
- }
-
- bindrc = Bind(sp->ns, &bindsock, sizeof(bindsock));
- if (bindrc < 0) {
- REPORT_TCP_ERROR(gp->ggserver);
- ERR2("TCP/IP error: bind() failed for socket %d", sp->ns);
- return FALSE;
- }
-
- ISPF("CONTROL DISPLAY LOCK");
- ISPF("DISPLAY PANEL(GGMLCONN)");
-
- if (gp->debug_file) {
- fprintf(gp->debug_file,
- "Client %s (%s) connecting to GOPHER server on %s (%s)\n",
- gp->client_hostname, gp->client_ip_addrstr,
- gp->server_hostname, gp->server_ip_addrstr);
- }
-
- connrc = Connect(sp->ns, &consock, sizeof(consock));
- if (connrc < 0) {
- REPORT_TCP_ERROR(gp->ggserver);
- ERR2("TCP/IP failure: connect() failed to connect to server %s.",
- gp->ggserver);
- return FALSE;
- }
-
- sp->connected_to_server = TRUE;
- sp->time_to_go_home = FALSE;
- sp->connection_broken = FALSE;
- sp->server_has_nothing = FALSE;
- sp->dont_read = FALSE;
-
- GGesrvr(gp,sp); /* Clean up any stray responses from server. */
-
- return TRUE;
-
- }
-
- ./ ADD NAME=GGCSO
-
- /********************************************************************/
- /* */
- /* Copyright (c) The Charles Stark Draper Laboratory, 1992, 1993 */
- /* GOPHER server due to Shawn Hart at the University of Delaware. */
- /* GOPHER client due to Steve Bacher at Draper Laboratory. */
- /* SAS modifications due to Dale Ingold at SAS Institute, Inc. */
- /* */
- /* This software is provided on an "AS IS" basis. All warranties, */
- /* including the implied warranties of merchantability and fitness, */
- /* are expressly denied. */
- /* */
- /* Provided this copyright notice is included, this software may */
- /* be freely distributed and not offered for sale. */
- /* */
- /* Changes or modifications may be made and used only by the maker */
- /* of same, and not further distributed. Such modifications should */
- /* be mailed to the author for consideration for addition to the */
- /* software and incorporation in subsequent releases. */
- /* */
- /********************************************************************/
-
- #pragma csect(code, "GG@CSO")
- #pragma csect(static,"GG$CSO")
- #include "gg.h"
-
- /********************************************************************
- *
- * The CSO code is due to:
- *
- * Lou Joseph <cwmy5c@irishmvs.cc.nd.edu>
- * Rachna Agrawal <rachna@clemson.clemson.edu>
- *
- ********************************************************************/
-
- /****** Gopher CSO interface. ************************************/
-
- Bool
- GGcso(gp,ip,as_file)
- RGGCB *gp;
- RINFO *ip;
- GOHOW as_file;
- {
- RCONN *sp;
- char *lp;
- char *rdel = ":";
- char *rtoken;
- char *rtok[5];
- char *rstr[14];
- int a; /* field counter */
- int b; /* field counter */
- int c; /* field counter */
- int d; /* field counter */
- int e_index_i;
- Bool got_some;
- char ggcsoq[14][256];
- char e_index_c[10];
- char sep[80] = "--------------------";
-
- sp = &gp->gopher_connection;
-
- strcpy(gp->ggserver,ip->host); /* Specify server to connect to */
-
- /***** set up fields command to server ***** start ******************/
-
- strcpy(gp->gopher_command,"fields");
-
- /***** set up fields command to server ***** end ******************/
-
- gp->ginfo = ip;
- if (!GGconn(gp,sp)) return FALSE; /* Connect to CSO server */
- GOPHERSEND(gp,sp); /* Send socket command */
- GGclrtx(gp,ip); /* Clear text */
-
- for (d = 0; d < 4; d++) rtok[d] = "";
- for (d = 0; d < 14; d++) rstr[d] = "";
-
- sp->receiving_text = TRUE;
- got_some = FALSE;
- a = 0; /* controls that each field is output only once */
- b = 0; /* counts the server line */
- c = 0; /* counts number of tokens in each new line */
- d = 0; /* counts that only some of the fields are saved */
- do {
- if (GGgsrvl(gp,sp,&lp,NOCR)) { /* Get server line */
- if (lp) {
- ++b;
- if (b == 2) {
- a = 1;
- b = 0;
- } /* end if (b == 2) */
- if (a == 1) { /* if new entry */
- c = 0;
- rtoken = strtok(lp,rdel);
- while (rtoken != NULL) {
- rtok[c] = rtoken;
- ++c;
- rtoken = strtok(NULL,rdel);
- } /* end while */
- a = 0;
- if (d < 14) {
- GETMAIN(rstr[d],char,strlen(rtok[2]+1),"CSO field string");
- if (!rstr[d]) break;
- strcpy(rstr[d], rtok[2]);
- ++d;
- }
- } /* end if new entry */
- got_some = TRUE;
- if (lp[0] != '-' && strncmp(lp,"200",3) >= 0) break;
- } /* end if lp */
- } /* end if GGgsrvl */
- } while (lp); /* until no more lines */
-
- if (!got_some) {
- WARN2("No data available from server %s.\n",gp->ggserver);
- return FALSE;
- }
-
- sp->receiving_text = FALSE;
-
- VPUT("FNAME1 ", rstr[0] );
- VPUT("FNAME2 ", rstr[1] );
- VPUT("FNAME3 ", rstr[2] );
- VPUT("FNAME4 ", rstr[3] );
- VPUT("FNAME5 ", rstr[4] );
- VPUT("FNAME6 ", rstr[5] );
- VPUT("FNAME7 ", rstr[6] );
- VPUT("FNAME8 ", rstr[7] );
- VPUT("FNAME9 ", rstr[8] );
- VPUT("FNAME10 ",rstr[9] );
- VPUT("FNAME11 ",rstr[10] );
- VPUT("FNAME12 ",rstr[11] );
- VPUT("FNAME13 ",rstr[12] );
- VPUT("FNAME14 ",rstr[13] );
-
- ISPF("VGET (FVALUE1) PROFILE");
-
- if (GGdispl(gp,"GGMCSO ") > 0) return FALSE;
-
- VGET("FVALUE1 ", ggcsoq[0] );
- VGET("FVALUE2 ", ggcsoq[1] );
- VGET("FVALUE3 ", ggcsoq[2] );
- VGET("FVALUE4 ", ggcsoq[3] );
- VGET("FVALUE5 ", ggcsoq[4] );
- VGET("FVALUE6 ", ggcsoq[5] );
- VGET("FVALUE7 ", ggcsoq[6] );
- VGET("FVALUE8 ", ggcsoq[7] );
- VGET("FVALUE9 ", ggcsoq[8] );
- VGET("FVALUE10 ",ggcsoq[9] );
- VGET("FVALUE11 ",ggcsoq[10] );
- VGET("FVALUE12 ",ggcsoq[11] );
- VGET("FVALUE13 ",ggcsoq[12] );
- VGET("FVALUE14 ",ggcsoq[13] );
-
- /***** set up query command to server ****** start ******************/
- strcpy(gp->gopher_command,"query ");
- if (!*ip->path) {
- for (a = 0; a < 14; a++)
- if (strlen(ggcsoq[a]) != 0) {
- strcat(gp->gopher_command + 6, rstr[a]);
- strcat(gp->gopher_command, "=\"");
- strcat(gp->gopher_command, ggcsoq[a]);
- strcat(gp->gopher_command, "\" ");
- }
- }
- else {
- sprintf(gp->gopher_command + 6,"%s\t",ip->path);
- for (a = 0; a < 14; a++) {
- strcat(gp->gopher_command + 6, rstr[a]);
- strcat(gp->gopher_command," =\"");
- strcat(gp->gopher_command, ggcsoq[a]);
- strcat(gp->gopher_command, "\" ");
- }
- }
- strcat(gp->gopher_command," return all");
-
- /***** set up query command to server ******* end *******************/
-
- GOPHERSEND(gp,sp); /* Send socket command */
- GGclrtx(gp,ip); /* Clear text */
-
- sp->receiving_text = TRUE;
- got_some = FALSE;
- e_index_i = 2;
- sprintf(e_index_c,":%u:",e_index_i);
- do {
- if (GGgsrvl(gp,sp,&lp,NOCR)) { /* Get server line */
- if (lp) {
- if (strstr(lp,e_index_c) != NULL) { /* if new entry */
- (void)GGouttx(gp,sep,ip,NO_VALUE); /* Output separator */
- ++e_index_i; /* Increment index */
- sprintf(e_index_c,":%u:",e_index_i);
- }
- got_some = TRUE;
- (void)GGouttx(gp,lp,ip,NO_VALUE); /* Output text line */
- if (lp[0] != '-' && strncmp(lp,"200",3) >= 0) break;
- }
- }
- } while (lp); /* until no more lines */
-
- if (!got_some) {
- WARN2("No data available from server %s.\n",gp->ggserver);
- return FALSE;
- }
-
- /* Send quit command */
-
- sp->receiving_text = FALSE;
- strcpy(gp->gopher_command,"quit");
- GOPHERSEND(gp,sp); /* Send socket command */
-
- /* Read Bye message */
-
- sp->receiving_text = TRUE;
-
- (void)GGgsrvl(gp,sp,&lp,NOCR); /* Get server line */
-
- if (sp->connected_to_server) {
- (void)GGdisc(gp,sp); /* Disconnect from CSO server */
- }
-
- GGvtx(gp,ip,as_file); /* display text from CSO server */
-
- for (d = 0; d < 14; d++) {
- if (*rstr[d]) {
- FREEMAIN(rstr[d],"CSO field string");
- }
- }
-
- return TRUE;
-
- }
-
- ./ ADD NAME=GGDBM
-
- /********************************************************************/
- /* */
- /* Copyright (c) The Charles Stark Draper Laboratory, 1992, 1993 */
- /* GOPHER server due to Shawn Hart at the University of Delaware. */
- /* GOPHER client due to Steve Bacher at Draper Laboratory. */
- /* SAS modifications due to Dale Ingold at SAS Institute, Inc. */
- /* */
- /* This software is provided on an "AS IS" basis. All warranties, */
- /* including the implied warranties of merchantability and fitness, */
- /* are expressly denied. */
- /* */
- /* Provided this copyright notice is included, this software may */
- /* be freely distributed and not offered for sale. */
- /* */
- /* Changes or modifications may be made and used only by the maker */
- /* of same, and not further distributed. Such modifications should */
- /* be mailed to the author for consideration for addition to the */
- /* software and incorporation in subsequent releases. */
- /* */
- /********************************************************************/
-
- #pragma csect(code, "GG@DBM ")
- #pragma csect(static,"GG$DBM ")
- #include "gg.h"
-
- /****** Delete a bookmark from a bookmark data set. ******************/
-
- Bool
- GGdbm(gp,ip)
- RGGCB *gp;
- RINFO *ip;
- {
- FILE *xfp;
- char *bufptr;
- char test [ 6];
- char dsname [129];
- char buffer [RBUFSIZE];
-
- if (!*ip->bmds) {
- WARN1("Delete not possible. This entry is not from a bookmark.");
- return FALSE;
- }
-
- VPUT("GGMDBMDS ",ip->bmds);
- VPUT("GGMDBMSU ",ip->desc);
-
- ISPF("ADDPOP");
-
- if (GGdispl(gp,"GGMPDBM ") > 0) {
- WARN1("Deletion cancelled, because you pressed END.");
- ISPF("REMPOP");
- return FALSE;
- }
-
- ISPF("REMPOP");
-
- sprintf(dsname,"'%s'",ip->bmds);
- xfp = fopen(dsname,"r");
- if (!xfp) {
- perror(dsname);
- ERR2("Cannot access bookmark data set %s.",dsname);
- return FALSE;
- }
-
- for (;;) {
- *buffer = '\0';
- fgets(buffer,sizeof(buffer),xfp);
- if (ferror(xfp)) {
- ERR2("Error reading bookmark data set %s.",dsname);
- break;
- }
- if (feof(xfp)) break;
- if ((bufptr=strchr(buffer,'\n'))) *bufptr = '\0';
- bufptr = skip_whitespace(buffer);
- CLEAR(test);
- memcpy(test,bufptr,5);
- uppercase_in_place(test);
-
- /*
- if (EQUAL(test,"TYPE="))
- else if (EQUAL(test,"NAME="))
- else if (EQUAL(test,"PATH="))
- else if (EQUAL(test,"HOST="))
- else if (EQUAL(test,"PORT="))
- else if (EQUAL(test,"END" ))
-
- */
-
- }
-
- (void)fclose(xfp);
-
- ERR1("Bookmark deletion is not yet supported, sorry.");
- return FALSE;
-
- }
-
- ./ ADD NAME=GGDFAIL
-
- /********************************************************************/
- /* */
- /* Copyright (c) The Charles Stark Draper Laboratory, 1992, 1993 */
- /* GOPHER server due to Shawn Hart at the University of Delaware. */
- /* GOPHER client due to Steve Bacher at Draper Laboratory. */
- /* SAS modifications due to Dale Ingold at SAS Institute, Inc. */
- /* */
- /* This software is provided on an "AS IS" basis. All warranties, */
- /* including the implied warranties of merchantability and fitness, */
- /* are expressly denied. */
- /* */
- /* Provided this copyright notice is included, this software may */
- /* be freely distributed and not offered for sale. */
- /* */
- /* Changes or modifications may be made and used only by the maker */
- /* of same, and not further distributed. Such modifications should */
- /* be mailed to the author for consideration for addition to the */
- /* software and incorporation in subsequent releases. */
- /* */
- /********************************************************************/
-
- #pragma csect(code, "GG@DFAIL")
- #pragma csect(static,"GG$DFAIL")
- #include "gg.h"
-
- /****** Retrieve allocation failure messages. ************************/
-
- void
- GGdfail(rc,p99)
- int rc;
- __S99parms *p99;
- {
- int zero = 0;
- unsigned int dfid = 0x40320000;
- struct {
- short first_level_msg_len;
- short first_level_msg_offset;
- char first_level_msg[251];
- short second_level_msg_len;
- short second_level_msg_offset;
- char second_level_msg[251];
- } dfbuffer;
-
- static int (*ikjeff18_pointer)() = NULL;
-
- #ifndef FETCH
- extern int *ikjeff18();
- #endif
-
- if (!ikjeff18_pointer) {
- #ifdef FETCH
- ikjeff18_pointer = (int (*)())fetch("IKJEFF18");
- #else
- ikjeff18_pointer = (int (*)())ikjeff18;
- #endif
- }
-
- dfbuffer.first_level_msg_len = 4;
- dfbuffer.second_level_msg_len = 4;
-
- if (ikjeff18_pointer) {
- if ((*ikjeff18_pointer)(p99,&rc,&zero,&dfid,&zero,&dfbuffer)) {
- fprintf(stderr,"IKJEFF18 returned a nonzero return code\n");
- }
- if (dfbuffer.first_level_msg_len > 0) {
- fprintf(stderr,"%*.*s\n",
- dfbuffer.first_level_msg_len-4,
- dfbuffer.first_level_msg_len-4,
- dfbuffer.first_level_msg);
- }
- if (dfbuffer.second_level_msg_len > 0) {
- fprintf(stderr,"%*.*s\n",
- dfbuffer.second_level_msg_len-4,
- dfbuffer.second_level_msg_len-4,
- dfbuffer.second_level_msg);
- }
- }
- else {
- #ifdef FETCH
- fprintf(stderr,"GGMVS: Cannot fetch IKJEFF18\n");
- #else
- fprintf(stderr,"Cannot call IKJEFF18, not linked with GGMVS\n");
- #endif
- }
- return;
- }
-
- ./ ADD NAME=GGDIR
-
- /********************************************************************/
- /* */
- /* Copyright (c) The Charles Stark Draper Laboratory, 1992, 1993 */
- /* GOPHER server due to Shawn Hart at the University of Delaware. */
- /* GOPHER client due to Steve Bacher at Draper Laboratory. */
- /* SAS modifications due to Dale Ingold at SAS Institute, Inc. */
- /* */
- /* This software is provided on an "AS IS" basis. All warranties, */
- /* including the implied warranties of merchantability and fitness, */
- /* are expressly denied. */
- /* */
- /* Provided this copyright notice is included, this software may */
- /* be freely distributed and not offered for sale. */
- /* */
- /* Changes or modifications may be made and used only by the maker */
- /* of same, and not further distributed. Such modifications should */
- /* be mailed to the author for consideration for addition to the */
- /* software and incorporation in subsequent releases. */
- /* */
- /********************************************************************/
-
- #pragma csect(code, "GG@DIR ")
- #pragma csect(static,"GG$DIR ")
- #include "gg.h"
-
- /*********************************************************************/
-
- static Bool
- valid_code(c)
- char c;
- {
-
- switch (c) {
- case GOPHER_FILE:
- case GOPHER_DIRECTORY:
- case GOPHER_TELNET:
- case GOPHER_TN3270:
- case GOPHER_WAIS:
- case GOPHER_WHOIS:
- case GOPHER_CSO:
- case GOPHER_ERROR:
- case GOPHER_BOOKMANAGER:
- case GOPHER_MAC_BINHEX:
- case GOPHER_DOS_BINARCH:
- case GOPHER_BINARY:
- case GOPHER_COMMENT:
- return TRUE;
- default: return FALSE;
- }
-
- }
-
- /*********************************************************************/
-
- static Bool
- process_s_selection(gp,ip)
- RGGCB *gp;
- RINFO *ip;
- {
-
- GGgofor(gp,ip,AS_NORMAL);
- return TRUE;
- }
-
- /*********************************************************************/
-
- static Bool
- process_i_selection(gp,ip)
- RGGCB *gp;
- RINFO *ip;
- {
-
- if (!GGinfo(gp,ip)) return FALSE;
- GGvtx(gp,NULL,AS_FILE);
- return TRUE;
- }
-
- /*********************************************************************/
-
- static Bool
- process_b_selection(gp,ip)
- RGGCB *gp;
- RINFO *ip;
- {
-
- if (!GGinfo(gp,ip)) return FALSE;
- gp->extract_file = NULL;
- GGxtx(gp,ip,BOOKMARK_IT);
- return TRUE;
- }
-
- /*********************************************************************/
-
- static Bool
- process_d_selection(gp,ip)
- RGGCB *gp;
- RINFO *ip;
- {
-
- return GGdbm(gp,ip);
- }
-
- /*********************************************************************/
-
- static Bool
- process_e_selection(gp,ip)
- RGGCB *gp;
- RINFO *ip;
- {
-
- if (!ip->thdr.first_text_line) {
- GGgofor(gp,ip,AS_NOTHING);
- }
- if (!ip->thdr.first_text_line) return FALSE;
- gp->extract_file = NULL;
- GGxtx(gp,ip,EXTRACT_IT);
- return TRUE;
- }
-
- /*********************************************************************/
-
- static Bool
- process_p_selection(gp,ip)
- RGGCB *gp;
- RINFO *ip;
- {
-
- if (!ip->thdr.first_text_line) {
- GGgofor(gp,ip,AS_NOTHING);
- }
- if (!ip->thdr.first_text_line) return FALSE;
- gp->extract_file = NULL;
- GGxtx(gp,ip,PRINT_IT);
- return TRUE;
- }
-
- /*********************************************************************/
-
- static Bool
- process_q_selection(gp,ip)
- RGGCB *gp;
- RINFO *ip;
- {
-
- GGgofor(gp,ip,AS_FILE);
- return TRUE;
- }
-
- /*********************************************************************/
-
- static Bool
- display_dynamic_area(gp,ip,infoarray,entrycount)
- RGGCB *gp;
- RINFO *ip;
- GOPHERINFO *infoarray;
- int entrycount;
- {
- GOPHERINFO *iap;
- int depth;
- int ggglvl;
- int dynsize;
- int topitem;
- int bottomitem;
- int last_item_selected;
- int dti;
- int gii;
- int prc;
- int l;
- int command_index;
- int zscrolln;
- int leftcol;
- int maxcol;
- int menucursor;
- Bool selok;
- Bool cmdok;
- Bool is_max;
- Bool is_csr;
- char *gggdyna;
- char *rowp;
- char *cp;
- char gggcmd [72];
- char zverb [9];
- char zscrolla [9];
- char command [COMMANDSIZE];
- char ggghead [81];
- char rowmessage [81];
-
- /* Get depth of dynamic area (number of rows to display on screen) */
-
- ISPF("PQUERY PANEL(GGMDIR) AREANAME(GGGDYNA) DEPTH(GGGDEPTH)");
- if (gp->ispfrc != 0) return FALSE;
- depth = IGET("GGGDEPTH ");
-
- /* Get storage for ISPF dynamic area variable to be constructed. */
-
- dynsize = 80*depth;
- GETMAIN(gggdyna, char, dynsize+1, "GGGDYNA buffer");
- if (!gggdyna) return FALSE;
-
- /* Loop displaying the panel until END pressed. */
-
- last_item_selected = -1;
- strcpy(gggcmd,"");
- topitem = 0;
- leftcol = 0;
- menucursor = 0;
- prc = 0;
- maxcol = 0;
- for (gii = 0; gii < entrycount; gii++) {
- l = strlen(infoarray[gii].desc);
- if (maxcol < l) maxcol = l;
- }
-
- while (prc == 0) {
-
- /* Fill in the dynamic area with rows, one for each gopher item. */
-
- memset(gggdyna,' ',dynsize);
- menucursor = 0;
-
- for (dti = 0, gii = topitem, rowp = gggdyna;
- dti < depth && gii < entrycount;
- dti++, gii++, rowp += 80) {
- iap = &infoarray[gii];
- if (gp->autocursor && gii == last_item_selected) {
- menucursor = rowp + 2 - gggdyna;
- }
- if (iap->type == GOPHER_COMMENT
- || iap->type == GOPHER_ERROR)
- rowp[ 0] = DATAOUT_HIGH; /* selection code protected */
- else
- rowp[ 0] = DATAIN_HIGH; /* selection code attribute */
- rowp[ 1] = ' '; /* selection code field */
- rowp[ 2] = DATAOUT_GREEN; /* icon attribute */
- memcpy(&rowp[ 3],GGtype(iap->type),9);
- rowp[12] = DATAOUT_HIGH; /* description attribute */
- l = strlen(iap->desc) - leftcol;
- if (l > 0) memcpy(&rowp[13], iap->desc + leftcol, l>67 ? 67 : l);
- }
-
- if (rowp < gggdyna + dynsize) {
- rowp[0] = DATAOUT_HIGH;
- memset(&rowp[1], '-',79);
- }
-
- bottomitem = gii - 1;
- if (topitem > bottomitem) strcpy(rowmessage,"");
- else sprintf(rowmessage, " %d-%d of %d",
- topitem + 1, bottomitem + 1, entrycount);
- memset(ggghead,' ',79);
- ggghead[79] = '\0';
- strcpy(ggghead,"GOPHER - ");
- strncpy(ggghead+9,ip->desc,70);
- *strchr(ggghead,'\0') = ' ';
- memcpy(ggghead+79-strlen(rowmessage),rowmessage,strlen(rowmessage));
-
- if (menucursor > 0) {
- IPUT("GGGCSR ", menucursor);
- }
- else VPUT("GGGCSR ", "0");
- VPUTS("GGGHEAD ",ggghead,79);
- VPUTS("GGGDYNA ",gggdyna, dynsize);
- VPUT ("GGGCMD " ,gggcmd);
-
- if ((prc=GGdispl(gp,"GGMDIR ")) > 8) break;
-
- VGETS("GGGDYNA " , gggdyna, dynsize);
- VGET ("ZVERB " , zverb);
- VGET ("ZSCROLLA ", zscrolla);
- zscrolln = IGET("ZSCROLLN ");
- ggglvl = IGET("GGGLVL ");
- last_item_selected = -1;
-
- /* Process selections. */
-
- for (gii = topitem, rowp = gggdyna;
- gii <= bottomitem;
- gii++, rowp += 80) {
- iap = &infoarray[gii];
- switch (toupper(rowp[1])) {
- case ' ': continue;
- case 'S': selok = process_s_selection(gp,iap); break;
- case 'E': selok = process_e_selection(gp,iap); break;
- case 'P': selok = process_p_selection(gp,iap); break;
- case 'Q': selok = process_q_selection(gp,iap); break;
- case 'I': selok = process_i_selection(gp,iap); break;
- case 'B': selok = process_b_selection(gp,iap); break;
- /* case 'D': selok = process_d_selection(gp,iap); break; */
- default:
- ERR1("Unknown selection code. Type one of the listed codes.");
- selok = FALSE; break;
- }
- if (selok) last_item_selected = gii;
- if (gp->quit) break;
- }
-
- /* Process command if any. */
-
- VGET("GGGCMD ",gggcmd);
- if (*gggcmd) {
- cmdok = TRUE;
- memset(command,' ',COMMANDSIZE);
- command_index = 0;
- for (cp = gggcmd; *cp && !isspace(*cp); cp++) {
- if (cp >= gggcmd+COMMANDSIZE) {
- ERR1(
- "Invalid command. Try \"OPTIONS\", \"MENU bookmarkname\", \"QUIT\"");
- cmdok = FALSE;
- }
- command[command_index++] = toupper(*cp);
- }
- while (*cp && isspace(*cp)) cp++;
- if (!memcmp(command,"QUIT ",8)) gp->quit = TRUE;
- else if (!memcmp(command,"MENU ",8)) GGmenu(gp,cp);
- else if (!memcmp(command,"OPT ",8)
- || !memcmp(command,"OPTION ",8)
- || !memcmp(command,"OPTIONS ",8)) GGdsopt(gp,cp);
- else if (!memcmp(command,"TEST ",8)) {
- gp->test_mode = TRUE;
- __ctest(NULL);
- }
- else {
- ERR1(
- "Unknown command. Try \"OPTIONS\", \"MENU bookmarkname\", \"QUIT\"");
- cmdok = FALSE;
- }
- if (cmdok) strcpy(gggcmd,"");
- }
-
- if (gp->quit) break;
-
- if (last_item_selected >= 0 && gp->autoscroll) {
- topitem = last_item_selected;
- }
-
- /* Process scroll request if any. */
-
- is_max = EQUAL(zscrolla,"MAX");
- is_csr = zscrolla[0] == 'C';
- if (EQUAL(zverb,"DOWN")) {
- if (is_max) topitem = entrycount - ggglvl;
- else topitem += zscrolln;
- }
- else if (EQUAL(zverb,"UP")) {
- if (is_max) topitem = 0;
- else topitem -= zscrolln;
- }
- else if (EQUAL(zverb,"LEFT")) {
- if (is_max) leftcol = 0;
- else leftcol -= zscrolln;
- }
- else if (EQUAL(zverb,"RIGHT")) {
- if (is_csr) zscrolln -= 13;
- if (is_max) leftcol = maxcol - 67;
- else leftcol += zscrolln;
- }
- else if (EQUAL(zverb,"RETURN")) {
- gp->quit = TRUE;
- break;
- }
- if (topitem < 0) topitem = 0;
- if (topitem > entrycount) topitem = entrycount;
- if (leftcol < 0) leftcol = 0;
- if (leftcol > maxcol) leftcol = maxcol;
-
- } /* end while prc == 0 */
-
- return;
-
- }
-
- /****** Gopher a directory. ******************************************/
-
- Bool
- GGdir(gp,ip,how)
- RGGCB *gp;
- RINFO *ip;
- GOHOW how;
- {
- int entrycount;
- int i;
- int copysize;
- char typechar;
- char savechar;
- char *p;
- char *q;
- char *r;
- TEXTLINE *tp;
- GOPHERINFO *infoarray;
- GOPHERINFO *iap;
- char temp [16];
-
- switch (how) {
- case AS_FILE: GGvtx(gp,ip,AS_FILE); /* display text as is */
- return TRUE;
- case AS_NOTHING: return TRUE; /* prepare for extract */
- case AS_NORMAL:
- default: break;
- }
-
- /* The text chain contains the data from the server, which should be
- * in the following format:
- *
- * nDescription^Path^foo^bar
- *
- * where the "n" in the beginning is a digit and ^ means a tab char.
- *
- * Logic:
- *
- * Build an array of gopherinfo structs from the text records.
- * Display them as an ISPF dynamic area pseudotable.
- * Let the user select them, and run GGgofor on each one
- * with a struct gopherinfo built from the contents.
- *
- */
-
- /* Determine size of array of gopherinfo structs. This is equal to
- * the number of text records with a valid code in the first byte.
- */
-
- entrycount = 0;
- for (tp = ip->thdr.first_text_line; tp; tp = tp->next) {
- if (valid_code(tp->text[0])) entrycount++;
- }
-
- if (entrycount == 0) {
- ERR1("There seems to be no information in this directory.\n");
- return FALSE;
- }
-
- /* Allocate an array of structs to hold the stuff. */
-
- GETMAIN(infoarray, struct gopherinfo, entrycount,"gopherinfo array");
-
- if (!infoarray) {
- ERR2("Not enough memory for %d gopher directory entries\n",
- entrycount);
- return FALSE;
- }
-
- /* Build the array entries. */
-
- iap = infoarray;
- for (tp = ip->thdr.first_text_line; tp; tp = tp->next) {
- typechar = tp->text[0];
- if (valid_code(typechar)) {
- r = &tp->text[tp->text_length];
- savechar = *r;
- *r = '\t';
- memset(iap,0,sizeof(struct gopherinfo));
- iap->port = GOPHER_PORT_NUMBER;
- iap->type = (GOPHERTYPE)typechar;
- p = &tp->text[1];
- q = strchr(p,'\t');
- copysize = sizeof(iap->desc)-1;
- if (copysize > q-p) copysize = q-p;
- memcpy(iap->desc,p,copysize);
- if (q < r) {
- p = q+1;
- q = strchr(p,'\t');
- copysize = sizeof(iap->path)-1;
- if (copysize > q-p) copysize = q-p;
- memcpy(iap->path,p,copysize);
- if (q < r) {
- p = q+1;
- q = strchr(p,'\t');
- copysize = sizeof(iap->host)-1;
- if (copysize > q-p) copysize = q-p;
- memcpy(iap->host,p,copysize);
- if (q < r) {
- p = q+1;
- q = strchr(p,'\t');
- memset(temp,0,sizeof(temp));
- copysize = sizeof(temp)-1;
- if (copysize > q-p) copysize = q-p;
- memcpy(temp,p,copysize);
- iap->port = atoi(temp);
- }
- }
- }
- strcpy(iap->bmds,gp->current_bookmark_ds);
- *r = savechar;
- iap++;
- }
- }
-
- if (gp->debug_mode) {
- for (iap = infoarray, i = entrycount; i > 0; iap++, i--) {
- fprintf(gp->debug_file,"GGdir: type = %d\n",iap->type);
- fprintf(gp->debug_file,"GGdir: port = %d\n",iap->port);
- fprintf(gp->debug_file,"GGdir: path = %s\n",iap->path);
- fprintf(gp->debug_file,"GGdir: host = %s\n",iap->host);
- fprintf(gp->debug_file,"GGdir: desc = %s\n",iap->desc);
- fprintf(gp->debug_file,"GGdir: bmds = %s\n",iap->bmds);
- fprintf(gp->debug_file,"\n");
- }
- }
-
- display_dynamic_area(gp,ip,infoarray,entrycount);
-
- FREEMAIN(infoarray,"gopherinfo array");
-
- return TRUE;
- }
-
- ./ ADD NAME=GGDISC
-
- /********************************************************************/
- /* */
- /* Copyright (c) The Charles Stark Draper Laboratory, 1992, 1993 */
- /* GOPHER server due to Shawn Hart at the University of Delaware. */
- /* GOPHER client due to Steve Bacher at Draper Laboratory. */
- /* SAS modifications due to Dale Ingold at SAS Institute, Inc. */
- /* */
- /* This software is provided on an "AS IS" basis. All warranties, */
- /* including the implied warranties of merchantability and fitness, */
- /* are expressly denied. */
- /* */
- /* Provided this copyright notice is included, this software may */
- /* be freely distributed and not offered for sale. */
- /* */
- /* Changes or modifications may be made and used only by the maker */
- /* of same, and not further distributed. Such modifications should */
- /* be mailed to the author for consideration for addition to the */
- /* software and incorporation in subsequent releases. */
- /* */
- /********************************************************************/
-
- #pragma csect(code, "GG@DISC ")
- #pragma csect(static,"GG$DISC ")
- #include "gg.h"
-
- /****** Disconnect from gopher server. ********************************/
-
- void
- GGdisc(gp,sp)
- RGGCB *gp;
- RCONN *sp;
- {
- RECV *R;
-
- /* If local mode, close temporary file and return. */
-
- if ((R=gp->recvp)) {
- if (R->outfp) {
- if (fclose(R->outfp) < 0) {
- CRIT1("Error closing local mode temporary file");
- }
- R->outfp = NULL;
- }
- sp->connected_to_server = FALSE;
- FREEMAIN(gp->recvp,"local mode recv struct");
- gp->recvp = NULL;
- return;
- }
-
- sp->closing_connection = TRUE;
-
- if (sp->connection_broken) {
- if (gp->debug_file) {
- fprintf(gp->debug_file,
- "Client %s (%s) connection with gopher server on %s (%s) was lost\n",
- gp->client_hostname,
- gp->client_ip_addrstr,
- gp->server_hostname,
- gp->server_ip_addrstr);
- }
- sp->connected_to_server = FALSE;
- }
- else {
-
- if (gp->debug_file) {
- fprintf(gp->debug_file,
- "Client %s (%s) disconnecting from gopher server on %s (%s)\n",
- gp->client_hostname,
- gp->client_ip_addrstr,
- gp->server_hostname,
- gp->server_ip_addrstr);
- }
-
- VPUT("GGSOLDER ",gp->server_hostname);
- VPUT("GGSOLDIP ",gp->server_ip_addrstr);
- ISPF("CONTROL DISPLAY LOCK");
- ISPF("DISPLAY PANEL(GGMLDISC)");
-
- GGesrvr(gp,sp); /* End server read */
-
- sp->connected_to_server = FALSE;
-
- if (close(sp->ns) < 0) {
- ERR2("TCP/IP error: close() failed to disconnect from server %s.",
- gp->ggserver);
- }
- }
-
- return;
- }
-
- ./ ADD NAME=GGDISPL
-
- /********************************************************************/
- /* */
- /* Copyright (c) The Charles Stark Draper Laboratory, 1992, 1993 */
- /* GOPHER server due to Shawn Hart at the University of Delaware. */
- /* GOPHER client due to Steve Bacher at Draper Laboratory. */
- /* SAS modifications due to Dale Ingold at SAS Institute, Inc. */
- /* */
- /* This software is provided on an "AS IS" basis. All warranties, */
- /* including the implied warranties of merchantability and fitness, */
- /* are expressly denied. */
- /* */
- /* Provided this copyright notice is included, this software may */
- /* be freely distributed and not offered for sale. */
- /* */
- /* Changes or modifications may be made and used only by the maker */
- /* of same, and not further distributed. Such modifications should */
- /* be mailed to the author for consideration for addition to the */
- /* software and incorporation in subsequent releases. */
- /* */
- /********************************************************************/
-
- #pragma csect(code, "GG@DISPL")
- #pragma csect(static,"GG$DISPL")
- #include "gg.h"
-
- #ifdef FETCH
- #define VL_BIT(X) ((unsigned int)(X) | 0x80000000)
- #else
- #define VL_BIT(X) (X)
- #endif
-
- /****** Display ISPF panel. ******************************************/
-
- int
- GGdispl(gp,pan8)
- RGGCB *gp;
- char *pan8;
- {
-
- if (gp->setmsg)
- gp->ispfrc = ISPLINK("DISPLAY ", pan8, VL_BIT("ISRZ002 "));
- else gp->ispfrc = ISPLINK("DISPLAY ", VL_BIT(pan8));
-
- if (gp->ispfrc > 8) GGierr(gp); /* display ISPF error */
- gp->setmsg = FALSE;
- return gp->ispfrc;
- }
-
- ./ ADD NAME=GGDSOPT
-
- /********************************************************************/
- /* */
- /* Copyright (c) The Charles Stark Draper Laboratory, 1992, 1993 */
- /* GOPHER server due to Shawn Hart at the University of Delaware. */
- /* GOPHER client due to Steve Bacher at Draper Laboratory. */
- /* SAS modifications due to Dale Ingold at SAS Institute, Inc. */
- /* */
- /* This software is provided on an "AS IS" basis. All warranties, */
- /* including the implied warranties of merchantability and fitness, */
- /* are expressly denied. */
- /* */
- /* Provided this copyright notice is included, this software may */
- /* be freely distributed and not offered for sale. */
- /* */
- /* Changes or modifications may be made and used only by the maker */
- /* of same, and not further distributed. Such modifications should */
- /* be mailed to the author for consideration for addition to the */
- /* software and incorporation in subsequent releases. */
- /* */
- /********************************************************************/
-
- #pragma csect(code, "GG@DSOPT")
- #pragma csect(static,"GG$DSOPT")
- #include "gg.h"
-
- /****** Set options. *************************************************/
-
- static void
- setoptions(gp,panelname,which)
- RGGCB *gp;
- char *panelname;
- OPTION which;
- {
-
- while (GGdispl(gp,panelname) == 0) {
- GGsopt(gp,which); /* Actually set options */
- }
-
- return;
- }
-
- /****** Option ... set GOPHER default processing options. ***********/
-
- void
- GGdsopt(gp,option)
- RGGCB *gp;
- char *option;
- {
- Bool force_choice = FALSE;
- char ggchoice [9];
-
- static char *message = "Invalid choice;\
- Move the cursor to a selection (or type S next to it) and press ENTER.";
-
- for (;;) {
- if (!force_choice && option && *option) {
- strncpy(ggchoice,option,sizeof(ggchoice)-1);
- }
- else {
- ISPF("ADDPOP");
- if (GGdispl(gp,"GGMPOPT ") > 0) {
- ISPF("REMPOP");
- break;
- }
- VGET("GGCHOICE ",ggchoice);
- if (*ggchoice == '?') ERR1(message);
- ISPF("REMPOP");
- }
- if (EQUAL(ggchoice,"1")) setoptions(gp,"GGMOPT1 ",OPTION_VIEW);
- else if (EQUAL(ggchoice,"2")) setoptions(gp,"GGMOPT2 ",OPTION_OTHER);
- else {
- ERR1(message);
- force_choice = TRUE;
- continue;
- }
- break;
- }
-
- return;
-
- }
-
- ./ ADD NAME=GGDUMP
-
- /********************************************************************/
- /* */
- /* Copyright (c) The Charles Stark Draper Laboratory, 1992, 1993 */
- /* GOPHER server due to Shawn Hart at the University of Delaware. */
- /* GOPHER client due to Steve Bacher at Draper Laboratory. */
- /* SAS modifications due to Dale Ingold at SAS Institute, Inc. */
- /* */
- /* This software is provided on an "AS IS" basis. All warranties, */
- /* including the implied warranties of merchantability and fitness, */
- /* are expressly denied. */
- /* */
- /* Provided this copyright notice is included, this software may */
- /* be freely distributed and not offered for sale. */
- /* */
- /* Changes or modifications may be made and used only by the maker */
- /* of same, and not further distributed. Such modifications should */
- /* be mailed to the author for consideration for addition to the */
- /* software and incorporation in subsequent releases. */
- /* */
- /********************************************************************/
-
- #pragma csect(code, "GG@DUMP ")
- #pragma csect(static,"GG$DUMP ")
- #include "gg.h"
-
- /****** Dump some data. **********************************************/
-
- void
- GGdump(GGCB *gp,
- char *label,
- char *p,
- int r)
- {
- int i;
-
- if (!gp->debug_file) return;
- switch (r) {
- case -2: fprintf(gp->debug_file,"%s: %d\n",label,(int)p); return;
- case -1: r = strlen(p); break;
- }
- fprintf(gp->debug_file,"%s: (%d characters)\n",label,r);
- fprintf(gp->debug_file, "---------------------------------------"
- "--------------------------------------\n");
- for (i=0;i<r;i++) {
- if (isprint(p[i])) fprintf(gp->debug_file,"%c",p[i]);
- else fprintf(gp->debug_file,"<0x%2.2x>",p[i]);
- }
- fprintf(gp->debug_file,"\n");
- fprintf(gp->debug_file, "---------------------------------------"
- "--------------------------------------\n");
- return;
-
- }
-
- ./ ADD NAME=GGESRVR
-
- /********************************************************************/
- /* */
- /* Copyright (c) The Charles Stark Draper Laboratory, 1992, 1993 */
- /* GOPHER server due to Shawn Hart at the University of Delaware. */
- /* GOPHER client due to Steve Bacher at Draper Laboratory. */
- /* SAS modifications due to Dale Ingold at SAS Institute, Inc. */
- /* */
- /* This software is provided on an "AS IS" basis. All warranties, */
- /* including the implied warranties of merchantability and fitness, */
- /* are expressly denied. */
- /* */
- /* Provided this copyright notice is included, this software may */
- /* be freely distributed and not offered for sale. */
- /* */
- /* Changes or modifications may be made and used only by the maker */
- /* of same, and not further distributed. Such modifications should */
- /* be mailed to the author for consideration for addition to the */
- /* software and incorporation in subsequent releases. */
- /* */
- /********************************************************************/
-
- #pragma csect(code, "GG@ESRVR")
- #pragma csect(static,"GG$ESRVR")
- #include "gg.h"
-
- /****** End server read. *********************************************/
-
- void
- GGesrvr(gp,sp)
- RGGCB *gp;
- RCONN *sp;
- {
- char *lp;
- Bool found_more_server_data = FALSE;
-
- if (!gp) return;
- GGclrtx(gp,NULL); /* Clear text */
- if (gp->recvp) return; /* Skip if non-socket */
-
- while (GGgsrvl(gp,sp,&lp,NOCR)) { /* Get server line */
- if (!lp) break;
- found_more_server_data = TRUE;
- (void)GGouttx(gp,lp,NULL,NO_VALUE); /* Output text line */
- }
-
- if (found_more_server_data) {
- ERR1("More data was returned by the GOPHER server than expected.");
- GGvtx(gp,NULL,TRUE); /* View text */
- }
-
- return;
- }
-
- ./ ADD NAME=GGFREEM
-
- /********************************************************************/
- /* */
- /* Copyright (c) The Charles Stark Draper Laboratory, 1992, 1993 */
- /* GOPHER server due to Shawn Hart at the University of Delaware. */
- /* GOPHER client due to Steve Bacher at Draper Laboratory. */
- /* SAS modifications due to Dale Ingold at SAS Institute, Inc. */
- /* */
- /* This software is provided on an "AS IS" basis. All warranties, */
- /* including the implied warranties of merchantability and fitness, */
- /* are expressly denied. */
- /* */
- /* Provided this copyright notice is included, this software may */
- /* be freely distributed and not offered for sale. */
- /* */
- /* Changes or modifications may be made and used only by the maker */
- /* of same, and not further distributed. Such modifications should */
- /* be mailed to the author for consideration for addition to the */
- /* software and incorporation in subsequent releases. */
- /* */
- /********************************************************************/
-
- #pragma csect(code, "GG@FREEM")
- #pragma csect(static,"GG$FREEM")
- #include "gg.h"
-
- /****** Free memory. *************************************************/
-
- void
- GGfreem(gp,stuff,whatfor)
- RGGCB *gp;
- char *stuff;
- char *whatfor;
- {
-
- free(stuff);
- if (gp && gp->debug_file) {
- fprintf(gp->debug_file,"GGfreem: freed memory for %s\n", whatfor);
- }
- return;
-
- }
-
- ./ ADD NAME=GGFTP
-
- /********************************************************************/
- /* */
- /* Copyright (c) The Charles Stark Draper Laboratory, 1992, 1993 */
- /* GOPHER server due to Shawn Hart at the University of Delaware. */
- /* GOPHER client due to Steve Bacher at Draper Laboratory. */
- /* SAS modifications due to Dale Ingold at SAS Institute, Inc. */
- /* */
- /* This software is provided on an "AS IS" basis. All warranties, */
- /* including the implied warranties of merchantability and fitness, */
- /* are expressly denied. */
- /* */
- /* Provided this copyright notice is included, this software may */
- /* be freely distributed and not offered for sale. */
- /* */
- /* Changes or modifications may be made and used only by the maker */
- /* of same, and not further distributed. Such modifications should */
- /* be mailed to the author for consideration for addition to the */
- /* software and incorporation in subsequent releases. */
- /* */
- /********************************************************************/
-
- #pragma csect(code, "GG@FTP")
- #pragma csect(static,"GG$FTP")
-
- #include "gg.h"
-
- /* Logic: use basic FTP protocol to get a directory or a file and
- * write the results to the passed file pointer.
- * Note: does not use PASV (win).
- */
-
- #define IPPORT_FTPD 20 /* FTP data port */
- #define IPPORT_FTP 21 /* FTP control port */
- #define SHOW(A) fprintf(stderr,"%s\n",(A))
- #define BLATHER if (F->verboseflag) fprintf
- #define FLOSE cleanup(F); return(FALSE)
- #define FSEND(A,B) if (!fsend(F,CS,(A),(B))) {FLOSE;}
- #define FRECV() if (!frecv(F,CS,TRUE)) {FLOSE;}
- #define FEXPECT(A) if (!fexpect(F,A)) {FLOSE;}
-
- /* ---- Format an FTP port address. -------------------------------- */
-
- static void
- port_address(
- struct Ftp *F, /* needed by BLATHER macro */
- IPADDRESS addrnum,
- int portnum,
- char *c
- )
- {
- char *ap = (char *)&addrnum;
- char *pp = (char *)&portnum;
-
- BLATHER(stderr,"port_address: addrnum=%8.8X, portnum=%8.8X\n",
- addrnum,portnum);
-
- sprintf(c,"%d,%d,%d,%d,%d,%d", (unsigned char)*(ap+0),
- (unsigned char)*(ap+1),
- (unsigned char)*(ap+2),
- (unsigned char)*(ap+3),
- (unsigned char)*(pp+2),
- (unsigned char)*(pp+3));
-
- return;
- }
-
- /* ---- Close socket. ---------------------------------------------- */
-
- static Bool
- ftp_close(
- struct Ftp *F,
- SOCKETNO s
- )
- {
-
- BLATHER(stderr,"Closing socket %d\n",s);
-
- if (close(s) < 0) {
- REPORT_TCP_ERROR("close");
- return FALSE;
- }
-
- return TRUE;
-
- }
-
- /* ---- Connect to the FTP server host. ---------------------------- */
-
- static SOCKETNO
- ftp_connect(
- struct Ftp *F,
- char *ftphost
- )
- {
- SOCKETNO ftpsock;
- int bindrc;
- int listrc;
- int connrc;
- char ipstring[65];
-
- ftpsock = -1;
- gethostname(F->client_hostname,sizeof(F->client_hostname));
- F->client_hostent = gethostbyname(F->client_hostname);
- if (!F->client_hostent) {
- REPORT_TCP_ERROR("gethostbyname for client hostname");
- return -1;
- }
- F->hostaddress = *(IPADDRESS *)F->client_hostent->h_addr_list[0];
-
- SPRINTF_IP_ADDRESS(ipstring,F->hostaddress);
- BLATHER(stderr,"client %s [%s]\n",F->client_hostname,ipstring);
-
- ftpsock = socket(AF_INET, SOCK_STREAM, 0);
- if (ftpsock < 0) {
- REPORT_TCP_ERROR("socket");
- return -1;
- }
-
- F->bindsock.sin_family = AF_INET;
- F->bindsock.sin_port = 0;
- F->bindsock.sin_addr.s_addr = F->hostaddress;
-
- bindrc = Bind(ftpsock,&F->bindsock,sizeof(F->bindsock));
- if (bindrc < 0) {
- REPORT_TCP_ERROR("bind for client");
- return -1;
- }
-
- F->server_hostent = gethostbyname(ftphost);
- if (!F->server_hostent) {
- fprintf(F->errfp,"gethostbyname: unknown host %s\n",ftphost);
- return -1;
- }
- F->hostaddress = *(IPADDRESS *)F->server_hostent->h_addr;
- strcpy(F->server_hostname,ftphost);
- SPRINTF_IP_ADDRESS(ipstring,F->hostaddress);
- BLATHER(stderr,"server %s [%s]\n",F->server_hostname,ipstring);
-
- F->consock.sin_family = AF_INET;
- F->consock.sin_port = htons(IPPORT_FTP);
- F->consock.sin_addr.s_addr = F->hostaddress;
-
- connrc = Connect(ftpsock,&F->consock,sizeof(F->consock));
- if (connrc < 0) {
- REPORT_TCP_ERROR(ftphost);
- return -1;
- }
-
- return ftpsock;
- }
-
- /* --- Get a response from the FTP server. ------------------ */
-
- static Bool
- frecv(F,S,doread)
- struct Ftp *F;
- CONNECTION *S;
- Bool doread;
- {
-
- S->dont_read = !doread;
- if (!GGgsrvl(NULL,S,NULL,NOCR)) return FALSE;
- if (S->time_to_go_home) return FALSE;
- if (S->server_has_nothing) return TRUE;
- if (F->verboseflag) SHOW(S->server_buf);
- return TRUE;
-
- }
-
- /* --- Send a request to the FTP server. ----------------------- */
-
- static Bool
- fsend(F,S,text,arg)
- struct Ftp *F;
- CONNECTION *S;
- char *text;
- char *arg;
- {
-
- /* check if there's anything pending from the server before sending */
-
- (void)frecv(F,S,FALSE);
- sprintf(S->client_buf,text,arg);
- if (F->verboseflag) SHOW(S->client_buf);
- return GGsockt(NULL,S);
- }
-
- /* --- Retrieve a response and insure it was the expected one. -- */
-
- static Bool
- fexpect(F,mesid)
- struct Ftp *F;
- char *mesid;
- {
- CONNECTION *S = &F->control_connection;
-
- for (;;) {
- if (!frecv(F,S,TRUE)) return FALSE;
- if (S->server_buf[0] == '\0') continue;
- if (S->server_buf[0] == ' ') continue;
- if (strlen(S->server_buf) > 3) {
- if (!memcmp(mesid,S->server_buf,3)) {
- if (S->server_buf[3] == '-') continue;
- if (S->server_buf[3] == '\0') break;
- if (S->server_buf[3] == ' ') break;
- }
- }
- fprintf(F->errfp,"Unexpected FTP response from %s:\n%s\n",
- F->server_hostname, S->server_buf);
- return FALSE;
- }
-
- return TRUE;
- }
-
- /*================================================================*/
-
- static GOPHERTYPE
- viewtype(char *fname)
- {
- int len = strlen(fname);
- int i;
-
- #define SUFFIX_TO_TYPE(A,B) i = sizeof(A)-1; \
- if (len > i && !memcmp(fname+len-i,A,i)) \
- return B;
-
- SUFFIX_TO_TYPE(".gif" ,GOPHER_IMAGE);
- SUFFIX_TO_TYPE(".pict" ,GOPHER_IMAGE);
- SUFFIX_TO_TYPE(".tiff" ,GOPHER_IMAGE);
- SUFFIX_TO_TYPE(".jpg" ,GOPHER_IMAGE);
- SUFFIX_TO_TYPE(".jpeg" ,GOPHER_IMAGE);
- SUFFIX_TO_TYPE(".hqx" ,GOPHER_MAC_BINHEX);
- SUFFIX_TO_TYPE(".arc" ,GOPHER_BINARY);
- SUFFIX_TO_TYPE(".exe" ,GOPHER_BINARY);
- SUFFIX_TO_TYPE(".EXE" ,GOPHER_BINARY);
- SUFFIX_TO_TYPE(".gz" ,GOPHER_BINARY);
- SUFFIX_TO_TYPE(".gzip" ,GOPHER_BINARY);
- SUFFIX_TO_TYPE(".hqx" ,GOPHER_BINARY);
- SUFFIX_TO_TYPE(".snd" ,GOPHER_BINARY);
- SUFFIX_TO_TYPE(".tar" ,GOPHER_BINARY);
- SUFFIX_TO_TYPE(".Z" ,GOPHER_BINARY);
- SUFFIX_TO_TYPE(".zip" ,GOPHER_BINARY);
- SUFFIX_TO_TYPE(".zoo" ,GOPHER_BINARY);
-
- return GOPHER_FILE;
- }
-
- /*================================================================*/
-
- static Bool
- ls_to_gopher(struct Ftp *F,
- char *buf,
- int *lenp
- )
-
- {
- #define NUMBER_OF_WORDS 12
- char *outnamep;
- char *word[NUMBER_OF_WORDS];
- char *cp;
- char *ep;
- char *name;
- char *symlink;
- char mode;
- int i;
- int maxwords;
- char outtype;
- char vmname [ 33];
- char empath [513];
- char rfile [513];
- char outname [513];
- char outpath [513];
-
- for (i = 0; i < NUMBER_OF_WORDS; i++) word[i] = "";
-
- /* Loop setting word[...] pointers to words in the buffer. */
-
- buf[*lenp] = '\0';
-
- /* Count the number of whitespace-delimited words on the line. */
-
- for (i = 0, cp = skip_whitespace(buf);
- i < NUMBER_OF_WORDS;
- cp = skip_whitespace(ep)) {
- word[i++] = cp;
- ep = strchr(cp,' ');
- if (!ep) break;
- }
-
- maxwords = i;
-
- /*
- * Normal Unix-style ls output:
- *
- * 0 1 2 3 4 5 6 7
- * mode block user size month day time name
- *
- * or
- *
- * 0 1 2 3 4 5 6 7 8
- * mode block user group size month day time name
- *
- * or
- *
- * 0 1 2 3 4 5 6 7 8 9 10
- * mode block user group size month day time name --> real
- *
- *
- * VM/CMS server output:
- *
- * 0 1 2 3 4 5 6 7 8
- * fname fmode ftype stuff stuff stuff date time disk?
- *
- */
-
- if (maxwords < 8) return FALSE;
- else if (F->os == VM_OS) {
- if ((ep=strchr(word[0],' '))) *ep = '\0';
- if ((ep=strchr(word[1],' '))) *ep = '\0';
- sprintf(vmname,"%s.%s",word[0],word[1]);
- mode = '-';
- name = vmname;
- symlink = "";
- }
- else {
- mode = *word[0];
- symlink = "";
- if (maxwords == 8) name = word[7];
- else if (isdigit(*word[4])) name = word[8];
- else name = word[7];
- if (mode == 'l' || mode == 'L') {
- ep = strstr(name," -> ");
- if (ep) {
- *ep = '\0';
- symlink = skip_whitespace(ep+3);
- }
- }
- }
-
- BLATHER(stderr,"maxwords=%d,name=%s,mode=%c,symlink=%s\n",
- maxwords,name,mode,symlink);
-
- if (!*name) return FALSE;
-
- #define PATH_SIZE_LIMIT 40
-
- if (strlen(F->path) > PATH_SIZE_LIMIT) {
- strcpy(empath, F->path + strlen(F->path) - PATH_SIZE_LIMIT);
- }
- else {
- strcpy(empath, F->path);
- }
-
- /*
- * Replace a symbolic link by the file to which it points. E.g.:
- *
- * /any-path -> /absolute/path ==> /absolute/path
- * /foo/bar/baz -> relative/path ==> /foo/bar/relative/path
- * /foo/bar/baz/ -> relative/path ==> /foo/bar/relative/path
- * foobar -> relative/path ==> relative/path
- *
- */
-
- if (*symlink) {
- if (symlink[0] == '/') strcpy(rfile,symlink);
- else {
- if (name[0] == '/') strcpy(rfile,name);
- else sprintf(rfile,"%s/%s",F->path,name);
- /* strcpy(rfile,F->path); */
- cp = strrchr(rfile,'/');
- if (cp && *(cp+1) == '\0') {
- *cp = '\0';
- cp = strrchr(rfile,'/');
- }
- if (!cp) cp = rfile-1;
- strcpy(cp+1,symlink);
- }
- sprintf(outname,"%s: %s: %s -> %s",F->host,empath,name,symlink);
- }
- else {
- if (name[0] == '/') strcpy(rfile,name);
- else sprintf(rfile,"%s/%s",F->path,name);
- sprintf(outname,"%s: %s: %s",F->host,empath,name);
- }
-
- switch (mode) {
- case '-': outtype = viewtype(rfile); break;
- case 'd':
- case 'D': outtype = GOPHER_MENU; break;
- case 'l':
- case 'L': outtype = GOPHER_MENU; break;
- default: BLATHER(stderr,"Unknown mode '%c'\n",mode); return FALSE;
- }
-
- if (strlen(outname) > 255) outnamep = outname + strlen(outname) - 255;
- else outnamep = outname;
-
- sprintf(outpath,"%s%c:%s:%s:%s:%s",
- F->ftphack, outtype, F->host, F->user, F->pass, rfile);
-
- sprintf(buf,"%c%s\t%s\t%s\t%d\n",
- outtype, outnamep, outpath, F->myname, F->myport);
-
- (*lenp) = strlen(buf);
-
- return TRUE;
- }
-
- /*================================================================*/
-
- static int
- emit(struct Ftp *F,
- char *buf,
- int len
- )
- {
- int fwriterc;
- Bool got_a_record;
- char newbuf [23448];
-
- memcpy(newbuf,buf,len);
-
- if (F->listflag) {
- got_a_record = ls_to_gopher(F,newbuf,&len);
- }
- else if (F->binary) {
- got_a_record = TRUE;
- }
- else {
- newbuf[len++] = '\n';
- got_a_record = TRUE;
- }
- if (got_a_record) {
- fwriterc = fwrite(newbuf,1,len,F->outfp);
- if (fwriterc < len) {
- fprintf(stderr,"Error writing to FTP output file\n");
- }
- }
- else fwriterc = 0;
-
- return fwriterc;
-
- }
-
- /*================================================================*/
-
- static void
- cleanup(struct Ftp *F)
- {
- CONNECTION *CS = &F->control_connection;
- CONNECTION *DS = &F->data_connection;
-
- if (F->listen_socket_opened) {
- (void)ftp_close(F,F->listensocket);
- F->listen_socket_opened = FALSE;
- }
-
- if (F->accept_socket_opened) {
- (void)ftp_close(F,DS->ns);
- F->accept_socket_opened = FALSE;
- }
-
- if (F->control_socket_opened) {
- (void)ftp_close(F,CS->ns);
- F->control_socket_opened = FALSE;
- }
-
- }
-
- /*================================================================*/
-
- Bool
- GGftp(RECV *R,
- struct Ftp *F
- )
- {
- CONNECTION *CS = &F->control_connection;
- CONNECTION *DS = &F->data_connection;
- char *ftpgetf = NULL;
- char *ftproot = NULL;
- char *cp;
- Bool rc = FALSE;
- int socksize;
- int accept_count;
- int bytes_to_write;
- int fwriterc;
- int bytes_written;
- IOMODE crmode;
- struct sockaddr_in datasocket;
- struct sockaddr_in controlsocket;
- char port [81];
- char control_server_buffer [SERVER_BUF_MSGSIZE+4];
- char data_server_buffer [SERVER_BUF_MSGSIZE+4];
- char control_client_buffer [CLIENT_BUF_MSGSIZE+4];
- char data_client_buffer [CLIENT_BUF_MSGSIZE+4];
-
- CLEAR(&datasocket);
- CLEAR(&controlsocket);
- CS->buf_index = -1;
- DS->buf_index = -1;
- CS->is_ftp = TRUE;
- DS->is_ftp = TRUE;
- CS->server_buf = control_server_buffer;
- DS->server_buf = data_server_buffer;
- CS->client_buf = control_client_buffer;
- DS->client_buf = data_client_buffer;
- F->myname = R->myname;
- F->myport = R->myport;
- F->control_socket_opened = FALSE;
- F->listen_socket_opened = FALSE;
- F->accept_socket_opened = FALSE;
-
- switch (F->type) {
- case GOPHER_DIRECTORY:
- F->listflag = TRUE; F->binary = FALSE; break;
- case GOPHER_MAC_BINHEX:
- case GOPHER_DOS_BINARCH:
- case GOPHER_IMAGE:
- case GOPHER_BINARY:
- case GOPHER_BOOKMANAGER:
- F->listflag = FALSE; F->binary = TRUE; break;
- case GOPHER_FILE:
- default:
- F->listflag = FALSE; F->binary = FALSE; break;
- }
-
- switch (F->os) {
- case VM_OS: if ((cp=strchr(F->path,'/'))) {
- *cp = '\0';
- ftproot = F->path;
- ftpgetf = cp + 1;
- }
- else {
- ftproot = F->path;
- ftpgetf = "";
- }
- break;
- default: ftproot = "";
- ftpgetf = F->path;
- break;
- }
-
- CS->ns = ftp_connect(F,F->host);
- if (CS->ns < 0) {FLOSE;}
- F->control_socket_opened = TRUE;
-
- BLATHER(stderr,"Connected to %s (socket %d).\n", F->host, CS->ns);
-
- FEXPECT("220"); /* server ready */
-
- FSEND("USER %s",F->user);
- FEXPECT("331"); /* password required */
-
- FSEND("PASS %s",F->pass);
- FEXPECT("230"); /* user logged in */
-
- /* must issue RETR command but open data connection first */
-
- F->listensocket = socket(AF_INET, SOCK_STREAM, 0);
- if (F->listensocket < 0) {
- REPORT_TCP_ERROR("data socket");
- FLOSE;
- }
- F->listen_socket_opened = TRUE;
-
- listen(F->listensocket,1); /* accept only one connection */
-
- /* get port number of data connection */
-
- socksize = sizeof(struct sockaddr);
- Getsockname(F->listensocket,&datasocket,&socksize);
- socksize = sizeof(struct sockaddr);
- Getsockname(CS->ns,&controlsocket,&socksize);
- datasocket.sin_addr.s_addr = controlsocket.sin_addr.s_addr;
-
- port_address(F,datasocket.sin_addr.s_addr,datasocket.sin_port,port);
-
- FSEND("PORT %s", port);
- FEXPECT("200"); /* command successful */
-
- if (F->binary) {
- crmode = RBIN;
- FSEND("TYPE %s","I"); /* image type */
- }
- else {
- crmode = NOCR;
- FSEND("TYPE %s","A"); /* ascii type */
- }
- FEXPECT("200"); /* type set to ... */
-
- if (*ftproot) {
- FSEND("CWD %s", ftproot);
- FEXPECT("250"); /* current working dir set to ... */
- }
-
- if (F->listflag) {
- if (!*ftpgetf) {FSEND("LIST", NULL);}
- else {FSEND("LIST %s", ftpgetf);}
- }
- else if (F->nlstflag) {
- if (!*ftpgetf) {FSEND("NLST", NULL);}
- else {FSEND("NLST %s", ftpgetf);}
- }
- else {
- FSEND("RETR %s", ftpgetf);
- }
- if (F->os == VM_OS && (F->listflag || F->nlstflag)) {
- FEXPECT("125"); /* List started OK */
- }
- else {
- FEXPECT("150"); /* data connection for... */
- }
-
- accept_count = 0;
- DS->ns = Accept(F->listensocket,NULL,&accept_count);
- if (DS->ns < 0) {
- REPORT_TCP_ERROR("accept");
- FLOSE;
- }
- F->accept_socket_opened = TRUE;
-
- /* get data from data connection */
-
- bytes_to_write = 0;
- bytes_written = 0;
- DS->time_to_go_home = FALSE;
- DS->server_has_nothing = FALSE;
- for (;;) {
- if (!GGgsrvl(NULL,DS,NULL,crmode)) {FLOSE;}
- if (DS->time_to_go_home || DS->server_has_nothing) break;
- if (crmode == RBIN) bytes_to_write = DS->nbytes;
- else bytes_to_write = strlen(DS->server_buf)-1;
- fwriterc = emit(F,DS->server_buf,bytes_to_write);
- bytes_written += fwriterc;
- }
-
- /* Close the data socket before waiting for the server to return
- * connection acknowledgement. The VM server enforces this.
- */
-
- (void)ftp_close(F,DS->ns);
- F->accept_socket_opened = FALSE;
-
- if (F->os == VM_OS) {
- FEXPECT("250"); /* ... completed successfully */
- }
- else {
- FEXPECT("226"); /* transfer complete */
- }
-
- FSEND("QUIT",NULL);
- FEXPECT("221"); /* goodbye */
-
- cleanup(F);
- return TRUE;
-
- }
-
- ./ ADD NAME=GGGETDS
-
- /********************************************************************/
- /* */
- /* Copyright (c) The Charles Stark Draper Laboratory, 1992, 1993 */
- /* GOPHER server due to Shawn Hart at the University of Delaware. */
- /* GOPHER client due to Steve Bacher at Draper Laboratory. */
- /* SAS modifications due to Dale Ingold at SAS Institute, Inc. */
- /* */
- /* This software is provided on an "AS IS" basis. All warranties, */
- /* including the implied warranties of merchantability and fitness, */
- /* are expressly denied. */
- /* */
- /* Provided this copyright notice is included, this software may */
- /* be freely distributed and not offered for sale. */
- /* */
- /* Changes or modifications may be made and used only by the maker */
- /* of same, and not further distributed. Such modifications should */
- /* be mailed to the author for consideration for addition to the */
- /* software and incorporation in subsequent releases. */
- /* */
- /********************************************************************/
-
- #pragma csect(code, "GG@GETDS")
- #pragma csect(static,"GG$GETDS")
- #include "gg.h"
- #include "ggsvc99.h"
-
- /****** Function to close sequential data set after extraction. ******/
-
- static void
- close_seq(gp,ep,xfp,final)
- RGGCB *gp;
- EXTRACTION *ep;
- FILE *xfp;
- Fool final;
- {
-
- if (fclose(xfp) < 0) {
- /* perror(ep->dsname); */
- ERR2("An error occurred closing %s.", ep->dsname);
- gp->extract_close_error = TRUE;
- }
-
- }
-
- /****** Function to close partitioned data set after extraction. *****/
-
- static void
- close_pds(gp,ep,xfp,final)
- RGGCB *gp;
- EXTRACTION *ep;
- FILE *xfp;
- Fool final;
- {
-
- if (final) {
- (void)GGunalc(ep->ddname); /* Unallocate the PDS */
- }
- else {
- if (fclose(xfp) < 0) {
- /* perror(ep->dsname); */
- ERR2("An error occurred closing %s.", ep->dsname);
- gp->extract_close_error = TRUE;
- }
- }
-
- }
-
- /****** Function to close SYSOUT print file after printing. **********/
-
- static void
- close_jes(gp,ep,xfp,final)
- RGGCB *gp;
- EXTRACTION *ep;
- FILE *xfp;
- Fool final;
- {
-
- if (fclose(xfp) < 0) {
- /* perror(ep->dsname); */
- ERR2("An error occurred closing %s.", ep->dsname);
- gp->extract_close_error = TRUE;
- }
- if (final) {
- (void)GGunalc(ep->ddname); /* Unallocate the SYSOUT file */
- }
-
- }
-
- /****** Allocate SYSOUT file. ****************************************/
-
- static Bool
- allocate_sysout(ep,sp)
- register EXTRACTION *ep;
- register SYSOUT *sp;
- {
- int i;
- int rc;
- char *cp;
- __S99parms stuff99; /* The manual has it wrong. No "struct". */
- TEXTUNIT *tu [ 8];
- TEXTUNIT tu_sysout;
- TEXTUNIT tu_copies;
- TEXTUNIT tu_dest;
- TEXTUNIT tu_userid;
- TEXTUNIT tu_forms;
- TEXTUNIT tu_ucs;
- TEXTUNIT tu_rtddn;
-
- CLEAR(&stuff99);
-
- stuff99.__S99RBLN = 20;
- stuff99.__S99VERB = S99VRBAL;
- stuff99.__S99FLAG1 = S99NOCNV << 8;
- stuff99.__S99ERROR = 0;
- stuff99.__S99INFO = 0;
- stuff99.__S99TXTPP = tu;
- stuff99.__S99FLAG2 = 0;
-
- i = 0;
-
- tu[i++] = &tu_sysout;
-
- tu_sysout.key = DALSYSOU;
- tu_sysout.num = 1;
- tu_sysout.ent.len = 1;
- tu_sysout.ent.prm[0] = toupper(sp->class[0]);
-
- tu[i++] = &tu_copies;
-
- tu_copies.key = DALCOPYS;
- tu_copies.num = 1;
- tu_copies.ent.len = 1;
- tu_copies.ent.prm[0] = (unsigned char)sp->copies;
-
- if (sp->dest[0] > ' ') {
-
- tu[i++] = &tu_dest;
-
- tu_dest.key = DALSUSER;
- tu_dest.num = 1;
- copy_uppercase_and_strip_trailing(tu_dest.ent.prm,sp->dest,cp);
- tu_dest.ent.len = cp - tu_dest.ent.prm;
-
- }
-
- if (sp->userid[0] > ' ') {
-
- tu[i++] = &tu_userid;
-
- tu_userid.key = DALUSRID;
- tu_userid.num = 1;
- copy_uppercase_and_strip_trailing(tu_userid.ent.prm,sp->userid,cp);
- tu_userid.ent.len = cp - tu_userid.ent.prm;
-
- }
-
- if (sp->forms[0] > ' ') {
-
- tu[i++] = &tu_forms;
-
- tu_forms.key = DALSFMNO;
- tu_forms.num = 1;
- copy_uppercase_and_strip_trailing(tu_forms.ent.prm,sp->forms,cp);
- tu_forms.ent.len = cp - tu_forms.ent.prm;
-
- }
-
- if (sp->ucs[0] > ' ') {
-
- tu[i++] = &tu_ucs;
-
- tu_ucs.key = DALUCS;
- tu_ucs.num = 1;
- copy_uppercase_and_strip_trailing(tu_ucs.ent.prm,sp->ucs,cp);
- tu_ucs.ent.len = cp - tu_ucs.ent.prm;
-
- }
-
- tu[i++] = &tu_rtddn;
-
- tu_rtddn.key = DALRTDDN;
- tu_rtddn.num = 1;
- tu_rtddn.ent.len = 8;
- memset(tu_rtddn.ent.prm,' ',8);
-
- tu[i] = (void *)0x80000000;
-
- rc = svc99(&stuff99);
-
- if (rc == 0) {
- memcpy(ep->ddname,(char *)tu_rtddn.ent.prm,8);
- ep->ddname[8] = ' ';
- *(strchr(ep->ddname,' ')) = '\0';
- return TRUE;
- }
- else {
- GGdfail(rc,&stuff99);
- return FALSE;
- }
- }
-
- /****** Prompt user for the name of a data set to extract into. ******/
-
- FILE *
- GGgetds(gp,ep)
- RGGCB *gp;
- REXTR *ep;
- {
- FILE *xfp;
- char *bufptr;
- Bool asked_for;
- Bool do_warn;
- Bool is_not_gopher_menu;
- SYSOUT sys;
- char ggexdsn [65]; /* data set name for extraction */
- char ggbmdsn [65]; /* data set name for bookmark */
- char ggexapp [4]; /* YES or NO for append mode */
- char ggextab [4]; /* YES or NO for tab expansion */
- char ggexblk [4]; /* YES or NO for blank after sep */
- char ggexsep [81]; /* Separator line (optional) */
- char ggexpmp [9]; /* PDS member name prefix */
- char ggexscl [2]; /* Print SYSOUT class name */
- char ggexsco [4]; /* Print SYSOUT copies number */
- char ggexsde [18]; /* Print SYSOUT destination */
- char ggexsus [18]; /* Print SYSOUT userid */
- char ggexsfo [5]; /* Print SYSOUT forms */
- char ggexsuc [5]; /* Print SYSOUT UCS */
- char ddname [9];
- char member [9];
- char pdspec [32];
- char quoted_dsname [67];
- char formatted_number [11];
- char buffer [RBUFSIZE];
-
- xfp = NULL;
- asked_for = TRUE;
-
- #ifdef FULLSYSOUT
- VPUT("GGALLPR ","Y");
- #else
- VPUT("GGALLPR ","");
- #endif
-
- ISPF("ADDPOP");
-
- while (!xfp) {
-
- /* Keep asking for a dsname until one works or END pressed. */
-
- if (GGdispl(gp,ep->panelname) > 0) {
- WARN1("Request cancelled, because you pressed END.");
- asked_for = FALSE;
- xfp = NULL;
- break;
- }
-
- switch (ep->ex) {
- case EXTRACT_IT:
- VGET("GGEXDSN ",ggexdsn);
- VGET("GGEXTAB ",ggextab);
- if (ep->mode == PDS) {
- VGET("GGEXPMP ",ggexpmp);
- }
- else {
- VGET("GGEXAPP ",ggexapp);
- VGET("GGEXBLK ",ggexblk);
- VGET("GGEXSEP ",ggexsep);
- }
- break;
- case PRINT_IT:
- VGET("GGEXSCL ",ggexscl);
- VGET("GGEXSCO ",ggexsco);
- #ifdef FULLSYSOUT
- VGET("GGEXSDE ",ggexsde);
- VGET("GGEXSUS ",ggexsus);
- VGET("GGEXSFO ",ggexsfo);
- VGET("GGEXSUC ",ggexsuc);
- #else
- *ggexsde = '\0';
- *ggexsus = '\0';
- *ggexsfo = '\0';
- *ggexsuc = '\0';
- #endif
- VGET("GGEXBLK ",ggexblk);
- VGET("GGEXSEP ",ggexsep);
- break;
- case BOOKMARK_IT:
- VGET("GGBMDSN ",ggbmdsn);
- break;
- }
-
- if (ep->mode == PDS) {
-
- ep->closer = close_pds;
- ep->appending = FALSE;
- ep->blanking = FALSE;
- strcpy(ep->separator,"");
- strcpy(ep->ddname,"");
- strcpy(ep->member_prefix,ggexpmp);
-
- /* Note: panel forces fully-qualified name to pass to allocate */
-
- if (ggexdsn[0] != '\'') {
- strcpy(quoted_dsname,"'");
- strcat(quoted_dsname,ggexdsn);
- strcat(quoted_dsname,"'");
- }
- else strcpy(quoted_dsname,ggexdsn);
-
- /* Check if PDS already exists. */
-
- if (gp->warn_overwrite) {
- if (TEST_IF_FILE_EXISTS(xfp,quoted_dsname)) {
- CLEANUP_IF_FILE_EXISTS(xfp);
- xfp = NULL;
- if (GGdispl(gp,"GGMPEXPW") > 0) {
- WARN1("Operation cancelled, because you pressed END.");
- break;
- }
- }
- }
-
- if (GGalloc(ggexdsn,ep->ddname,PDS,ep->count) != PDS) {
- ERR2("Allocation failed for data set %s.", ggexdsn);
- xfp = NULL;
- continue;
- }
- strcpy(ep->dsname, ggexdsn);
- ep->tab_expanding = (ggextab[0] == 'Y');
- do_warn = (ep->appending ? gp->warn_append : gp->warn_overwrite);
- }
- else if (ep->mode == JES) {
- if (strlen(ggexsde) > 8) {
- ERR2("SYSOUT destination is too long: %s", ggexsde);
- xfp = NULL;
- continue;
- }
- if (strlen(ggexsus) > 8) {
- ERR2("SYSOUT userid is too long: %s", ggexsus);
- xfp = NULL;
- continue;
- }
- ep->closer = close_jes;
- strcpy(ep->separator, ggexsep);
- sprintf(ep->dsname,"SYSOUT class %s",ggexscl);
- strcpy(sys.class, ggexscl);
- sys.copies = atoi(ggexsco);
- if (sys.copies < 1) sys.copies = 1;
- strcpy(sys.dest, ggexsde);
- strcpy(sys.userid,ggexsus);
- strcpy(sys.forms, ggexsfo);
- strcpy(sys.ucs, ggexsuc);
- ep->appending = FALSE;
- ep->blanking = (ggexblk[0] == 'Y');
- ep->tab_expanding = TRUE;
- do_warn = FALSE;
- }
- else if (ep->ex == BOOKMARK_IT) {
- ep->closer = close_seq;
- strcpy(ep->separator, "");
- strcpy(ep->dsname, ggbmdsn);
- strcpy(ggexdsn, ggbmdsn);
- ep->appending = TRUE;
- ep->blanking = FALSE;
- ep->tab_expanding = FALSE;
- do_warn = FALSE;
- }
- else {
- ep->closer = close_seq;
- strcpy(ep->separator, ggexsep);
- strcpy(ep->dsname, ggexdsn);
- ep->appending = (ggexapp[0] == 'Y');
- ep->blanking = (ggexblk[0] == 'Y');
- ep->tab_expanding = (ggextab[0] == 'Y');
- do_warn = (ep->appending ? gp->warn_append : gp->warn_overwrite);
- }
-
- /* check if the dataset already exists */
-
- if (ep->ex == BOOKMARK_IT) {
- is_not_gopher_menu = FALSE;
- if (TEST_IF_FILE_EXISTS(xfp,ggexdsn)) {
- /* check that it is a gopher menu */
- CLEANUP_IF_FILE_EXISTS(xfp);
- xfp = fopen(ggexdsn,"r");
- if (xfp) {
- *buffer = '\0';
- fgets(buffer,sizeof(buffer),xfp);
- if (*buffer) {
- if ((bufptr=strchr(buffer,'\n'))) *bufptr = '\0';
- uppercase_in_place(buffer);
- bufptr = skip_whitespace(buffer);
- if (!EQUAL(bufptr,MENUIDENT)) is_not_gopher_menu = TRUE;
- }
- (void)fclose(xfp);
- xfp = NULL;
- }
- if (is_not_gopher_menu) {
- WARN2("Not a gopher bookmark or menu file: %s",ep->dsname);
- break;
- }
- ep->appending = TRUE;
- }
- else {
- ep->appending = FALSE;
- }
- }
- else if (ep->mode != JES) {
- if (do_warn) {
- if (TEST_IF_FILE_EXISTS(xfp,ggexdsn)) {
- CLEANUP_IF_FILE_EXISTS(xfp);
- xfp = NULL;
- if (GGdispl(gp,"GGMPEXOW") > 0) {
- WARN1("Operation cancelled, because you pressed END.");
- break;
- }
- }
- }
- }
-
- if (ep->mode == JES) {
- if (allocate_sysout(ep,&sys)) {
- sprintf(ggexdsn,"dd:%s",ep->ddname);
- }
- else *ggexdsn = '\0';
- }
-
- if (ep->mode == PDS) {
- xfp = DUMMY_FILE_POINTER;
- break;
- }
-
- if (*ggexdsn) {
-
- if (ep->mode == JES) {
- xfp = OPEN_SYSOUT_FILE(ggexdsn);
- }
- else {
- xfp = OPEN_TEXT_FILE_FOR_WRITE_OR_APPEND(ggexdsn,ep->appending);
- }
-
- if (!xfp) {
- #ifdef SNSTCPIP
- fprintf(stderr,"Open failure: errno=%d\n",GET_ERRNO);
- #else
- fprintf(stderr,"Open failure: errno=%d\n",errno);
- #endif
- perror(ggexdsn);
- ERR2("Cannot open data set %s.", ep->dsname);
- }
- }
- }
-
- ISPF("REMPOP");
-
- return xfp;
-
- }
-
- ./ ADD NAME=GGGETM
-
- /********************************************************************/
- /* */
- /* Copyright (c) The Charles Stark Draper Laboratory, 1992, 1993 */
- /* GOPHER server due to Shawn Hart at the University of Delaware. */
- /* GOPHER client due to Steve Bacher at Draper Laboratory. */
- /* SAS modifications due to Dale Ingold at SAS Institute, Inc. */
- /* */
- /* This software is provided on an "AS IS" basis. All warranties, */
- /* including the implied warranties of merchantability and fitness, */
- /* are expressly denied. */
- /* */
- /* Provided this copyright notice is included, this software may */
- /* be freely distributed and not offered for sale. */
- /* */
- /* Changes or modifications may be made and used only by the maker */
- /* of same, and not further distributed. Such modifications should */
- /* be mailed to the author for consideration for addition to the */
- /* software and incorporation in subsequent releases. */
- /* */
- /********************************************************************/
-
- #pragma csect(code, "GG@GETM ")
- #pragma csect(static,"GG$GETM ")
- #include "gg.h"
-
- /****** Get memory. **************************************************/
-
- void
- GGgetm(gp,pointer,howmuch,whatfor)
- RGGCB *gp;
- char **pointer;
- int howmuch;
- char *whatfor;
- {
-
- *pointer = (char *)malloc(howmuch);
-
- if (!*pointer) {
- fprintf(stderr,"GGgetm: Cannot obtain %d bytes of memory for %s\n",
- howmuch,whatfor);
- }
- else if (gp && gp->debug_file) {
- fprintf(gp->debug_file,"GGgetm: got %d bytes of memory for %s\n",
- howmuch,whatfor);
- }
- return;
-
- }
-
- ./ ADD NAME=GGGOFOR
-
- /********************************************************************/
- /* */
- /* Copyright (c) The Charles Stark Draper Laboratory, 1992, 1993 */
- /* GOPHER server due to Shawn Hart at the University of Delaware. */
- /* GOPHER client due to Steve Bacher at Draper Laboratory. */
- /* SAS modifications due to Dale Ingold at SAS Institute, Inc. */
- /* */
- /* This software is provided on an "AS IS" basis. All warranties, */
- /* including the implied warranties of merchantability and fitness, */
- /* are expressly denied. */
- /* */
- /* Provided this copyright notice is included, this software may */
- /* be freely distributed and not offered for sale. */
- /* */
- /* Changes or modifications may be made and used only by the maker */
- /* of same, and not further distributed. Such modifications should */
- /* be mailed to the author for consideration for addition to the */
- /* software and incorporation in subsequent releases. */
- /* */
- /********************************************************************/
-
- #pragma csect(code, "GG@GOFOR")
- #pragma csect(static,"GG$GOFOR")
- #include "gg.h"
-
- /********************************************************************/
-
- static Bool
- connect_and_get_data_from_gopher_server(gp,sp,ip,crmode)
- RGGCB *gp;
- RCONN *sp;
- RINFO *ip;
- IOMODE crmode;
- {
- char *lp;
- Bool got_some;
-
- strcpy(gp->ggserver,ip->host); /* Specify server to connect to */
- strcpy(gp->gopher_command,ip->path); /* Specify command to issue */
- gp->ginfo = ip;
- sp->receiving_text = FALSE;
-
- if (!GGconn(gp,sp)) return FALSE; /* Connect to gopher server */
- GOPHERSEND(gp,sp); /* Send socket command */
- GGclrtx(gp,ip); /* Clear text */
-
- sp->receiving_text = TRUE;
- got_some = FALSE;
- while (GGgsrvl(gp,sp,&lp,crmode)) { /* Get server line */
- if (!lp) break;
- got_some = TRUE;
- (void)GGouttx(gp,lp,ip, /* Output text line */
- crmode == RBIN ? sp->nbytes : NO_VALUE);
- }
-
- if (!got_some) {
- WARN2("No data available from server %s.\n",gp->ggserver);
- return FALSE;
- }
-
- return TRUE;
- }
-
- /****** Gopher it. ***************************************************/
-
- Bool
- GGgofor(gp,ip,how)
- RGGCB *gp;
- RINFO *ip;
- GOHOW how;
- {
- RCONN *sp = &gp->gopher_connection;
- Bool (*fun)(GGCB *, GOPHERINFO *, GOHOW);
- Bool con;
- Bool rc;
- IOMODE cr;
- char savebook[63];
-
- /* (1) send initial path string to initial host
- * (2) get back data from host
- * (3) if it is a gopher directory, then do:
- * - display "table" of items
- * - for each item selected, call GGgofor recursively
- * else browse the file data
- * (4) bye
- */
-
- if (gp->debug_mode) {
- fprintf(gp->debug_file,"GGgofor: type = %c\n",ip->type);
- fprintf(gp->debug_file,"GGgofor: port = %d\n",ip->port);
- fprintf(gp->debug_file,"GGgofor: path = %s\n",ip->path);
- fprintf(gp->debug_file,"GGgofor: host = %s\n",ip->host);
- fprintf(gp->debug_file,"GGgofor: desc = %s\n",ip->desc);
- fprintf(gp->debug_file,"GGgofor: bmds = %s\n",ip->bmds);
- }
-
- switch (ip->type) {
- case GOPHER_FILE: fun = GGvtx; con = TRUE; cr = CRLF; break;
- case GOPHER_DIRECTORY: fun = GGdir; con = TRUE; cr = CRLF; break;
- case GOPHER_TELNET: fun = GGtnet; con = FALSE; cr = CRLF; break;
- case GOPHER_TN3270: fun = GGtnet; con = FALSE; cr = CRLF; break;
- case GOPHER_WAIS: fun = GGwais; con = FALSE; cr = CRLF; break;
- case GOPHER_WHOIS: fun = GGwhois; con = FALSE; cr = CRLF; break;
- case GOPHER_CSO: fun = GGcso; con = FALSE; cr = NOCR; break;
- case GOPHER_BOOKMANAGER:fun = GGbkmgr; con = TRUE; cr = RBIN; break;
- case GOPHER_MAC_BINHEX:
- case GOPHER_DOS_BINARCH:
- case GOPHER_BINARY: fun = GGbin; con = TRUE; cr = RBIN; break;
- case GOPHER_ERROR: return TRUE;
- case GOPHER_COMMENT: return TRUE;
- default:
- ERR2("Sorry, accessing an item of type %s is not supported",
- GGtype(ip->type));
- return FALSE;
- }
-
- if (con) {
- rc = connect_and_get_data_from_gopher_server(gp,sp,ip,cr);
- }
-
- /* Insure no connection is active once we do the real thing. */
-
- if (sp->connected_to_server) {
- (void)GGdisc(gp,sp); /* Disconnect from gopher server */
- }
-
- if (!rc) return FALSE; /* Fail if could not get data */
-
- strcpy(savebook,gp->current_bookmark_ds);
- if (EQUAL(ip->host, LOCAL_HOST_FROB)) {
- strncpy(gp->current_bookmark_ds,ip->path,sizeof(savebook));
- }
- else {
- strcpy(gp->current_bookmark_ds,"");
- }
-
- rc = (fun)(gp,ip,how);
-
- strcpy(gp->current_bookmark_ds,savebook);
-
- return rc;
-
- }
-
- ./ ADD NAME=GGGSRVL
-
- /********************************************************************/
- /* */
- /* Copyright (c) The Charles Stark Draper Laboratory, 1992, 1993 */
- /* GOPHER server due to Shawn Hart at the University of Delaware. */
- /* GOPHER client due to Steve Bacher at Draper Laboratory. */
- /* SAS modifications due to Dale Ingold at SAS Institute, Inc. */
- /* */
- /* This software is provided on an "AS IS" basis. All warranties, */
- /* including the implied warranties of merchantability and fitness, */
- /* are expressly denied. */
- /* */
- /* Provided this copyright notice is included, this software may */
- /* be freely distributed and not offered for sale. */
- /* */
- /* Changes or modifications may be made and used only by the maker */
- /* of same, and not further distributed. Such modifications should */
- /* be mailed to the author for consideration for addition to the */
- /* software and incorporation in subsequent releases. */
- /* */
- /********************************************************************/
-
- #pragma csect(code, "GG@GSRVL")
- #pragma csect(static,"GG$GSRVL")
- #include "gg.h"
-
- /****** Input one character from the server. *************************/
-
- static int
- socket_getchar(sp,crmode)
- RCONN *sp;
- IOMODE crmode;
- {
- int readrc;
-
- if (sp->buf_index == -1 || sp->buf_index >= sp->bytes_returned - 1) {
- sp->buf_index = -1;
- if (sp->dont_read) return SOCKET_NO_MORE;
- TCP_DEBUG_ON;
- readrc = read(sp->ns, sp->buf, READ_BYTES);
- TCP_DEBUG_OFF;
- if (readrc == -1) {
- sp->connection_broken = TRUE;
- return SOCKET_GETCHAR_ERROR;
- }
- else if (readrc == 0) {
- sp->connection_broken = FALSE;
- return SOCKET_READ_NOTHING;
- }
- else {
- if (crmode != RBIN) {
- ASCII_TO_EBCDIC(sp->buf,readrc);
- }
- sp->bytes_returned = readrc;
- }
- }
- return sp->buf[++sp->buf_index];
- }
-
- /****** Input one data line at a time from the server. ***************/
-
- static RETVAL
- socket_from_server(gp,sp,crmode)
- RGGCB *gp;
- RCONN *sp;
- IOMODE crmode;
- {
- char *s_buf = sp->server_buf;
- int s_bytes = SERVER_BUF_MSGSIZE;
- int s_buf_index = 0;
- int previous_character = -1;
- int character;
-
- /* Get characters from the server until LF is reached. */
-
- for (;;) {
- sp->nbytes = s_buf_index;
- if (crmode == RBIN && s_buf_index >= s_bytes) break;
- character = socket_getchar(sp,crmode);
- if (character == LINE_FEED && crmode != RBIN) break;
- if (character == SOCKET_GETCHAR_ERROR) return SERVER_READ_ERROR;
- if (character == SOCKET_NO_MORE) return SERVER_NO_MORE;
- if (character == SOCKET_READ_NOTHING) return SERVER_READ_NOTHING;
- previous_character = character;
- if (s_buf_index >= s_bytes) {
- fprintf(stderr,
- "Error: More than %d bytes received without Line Feed.\n",
- s_bytes);
- if (gp && gp->debug_file) {
- GGdump(gp,"Data collected so far",sp->server_buf,s_bytes);
- }
- return SERVER_BUFFER_ERROR;
- }
- if (crmode != RBIN && character == '\0' && !sp->is_ftp) {
- fprintf(stderr,
- "Warning: null character found in server data, changed to blank\n");
- character = ' ';
- }
- s_buf[s_buf_index++] = (unsigned char)character;
- }
- s_buf[s_buf_index] = '\0';
- return SERVER_READ_OK;
- }
-
- /****** Get server line. *********************************************/
-
- Bool
- GGgsrvl(gp,sp,pointer,crmode)
- RGGCB *gp;
- RCONN *sp;
- char **pointer;
- IOMODE crmode;
- {
- RRECV *R;
- char *sbufp;
- char *p;
- int scan_count;
- Bool something_to_print;
- RETVAL sfs;
-
- if (pointer) *pointer = NULL;
-
- /* If local mode, read from temporary file until EOF. */
-
- if (gp && (R=gp->recvp) && !sp->is_ftp) {
- if (!R->outfp) {
- CRIT1("Can't read data locally, non-socket not connected\n");
- return FALSE;
- }
- if (crmode == RBIN) {
- sp->nbytes =
- fread(sp->server_buf,sizeof(char),SERVER_BUF_MSGSIZE,R->outfp);
- if (ferror(R->outfp)) {
- CRIT1("Error reading local non-socket data\n");
- sp->time_to_go_home = TRUE;
- return FALSE;
- }
- if (sp->nbytes <= 0) return FALSE;
- if (pointer) *pointer = sp->server_buf;
- return TRUE;
- }
- else {
- fgets(sp->server_buf, SERVER_BUF_MSGSIZE, R->outfp);
- if (ferror(R->outfp)) {
- CRIT1("Error reading local non-socket data\n");
- sp->time_to_go_home = TRUE;
- return FALSE;
- }
- if ((p=strchr(sp->server_buf,'\n'))) *p = '\0';
- if (pointer) *pointer = sp->server_buf;
- if (feof(R->outfp)) return FALSE;
- return TRUE;
- }
- }
-
- if (sp->is_ftp) {
-
- sp->time_to_go_home = FALSE;
- sp->server_has_nothing = FALSE;
-
- switch (socket_from_server(gp,sp,crmode)) {
- case SERVER_READ_OK: return TRUE;
- case SERVER_READ_NOTHING: if (crmode == RBIN) sp->dont_read = TRUE;
- else sp->server_has_nothing = TRUE;
- return TRUE;
- case SERVER_NO_MORE: sp->server_has_nothing = TRUE;
- return TRUE;
- case SERVER_READ_ERROR: fprintf(stderr,
- "Lost server connection. Failure reading data from server %s.",
- sp->server_hostname);
- sp->time_to_go_home = TRUE;
- return FALSE;
- case SERVER_BUFFER_ERROR: fprintf(stderr,
- "Read error. No linefeed character found in data from server %s.",
- sp->server_hostname);
- sp->time_to_go_home = TRUE;
- return FALSE;
- }
- }
-
- if (!sp->receiving_text) return TRUE;
- if (sp->server_finished_replying) sp->dont_read = TRUE;
-
- sfs = socket_from_server(gp,sp,crmode);
- switch (sfs) {
- case SERVER_READ_OK: break;
- case SERVER_READ_NOTHING: if (crmode == RBIN) sp->dont_read = TRUE;
- else sp->time_to_go_home = TRUE;
- break;
- case SERVER_READ_ERROR: ERR2(
- "Lost server connection. Failure reading data from server %s.",
- sp->server_hostname);
- sp->time_to_go_home = TRUE;
- break;
- case SERVER_BUFFER_ERROR: ERR2(
- "Read error. No linefeed character found in data from server %s.",
- sp->server_hostname);
- sp->time_to_go_home = TRUE;
- break;
- case SERVER_NO_MORE: sp->server_has_nothing = TRUE;
- break;
- }
-
- if (sp->time_to_go_home) return FALSE;
- if (sp->dont_read && sp->server_has_nothing) return TRUE;
-
- something_to_print = TRUE;
- sbufp = sp->server_buf;
-
- if (sp->sending_text && crmode != RBIN) {
- if (*sbufp == '.') {
- switch (*(sbufp+1)) {
- case CARRIAGE_RETURN:
- case LINE_FEED:
- case '\0':
- sp->server_finished_replying = TRUE;
- something_to_print = FALSE;
- break;
- case '.':
- break;
- default: if (gp) {
- GGdump(gp,"Warning, bad period in line from server",
- sbufp,strlen(sbufp));
- }
- break;
- }
- }
- }
-
- sp->sending_text = TRUE;
-
- if (something_to_print) {
- /* Last character of output buffer is a CR without LF. */
- if (crmode != RBIN) {
- p = sbufp + strlen(sbufp)-1;
- if (p >= sbufp) {
- if (*p == CARRIAGE_RETURN) *p = '\0';
- else if (crmode == CRLF) {
- /* Last character of output buffer had better be a LF. */
- if (gp && gp->debug_file) {
- fprintf(gp->debug_file,
- "Warning: No carriage return in data from server (%d bytes):\n%s\n",
- strlen(sbufp), sbufp);
- }
- CRIT2(
- "Carriage return expected but not seen in data from server %s.",
- sp->server_hostname);
- }
- *(p+1) = '\0';
- sp->nbytes = (p+1) - sbufp;
- }
- }
- if (pointer) *pointer = sbufp;
- }
-
- if (sp->time_to_go_home) return FALSE;
- else return TRUE;
- }
-
- ./ ADD NAME=GGIERR
-
- /********************************************************************/
- /* */
- /* Copyright (c) The Charles Stark Draper Laboratory, 1992, 1993 */
- /* GOPHER server due to Shawn Hart at the University of Delaware. */
- /* GOPHER client due to Steve Bacher at Draper Laboratory. */
- /* SAS modifications due to Dale Ingold at SAS Institute, Inc. */
- /* */
- /* This software is provided on an "AS IS" basis. All warranties, */
- /* including the implied warranties of merchantability and fitness, */
- /* are expressly denied. */
- /* */
- /* Provided this copyright notice is included, this software may */
- /* be freely distributed and not offered for sale. */
- /* */
- /* Changes or modifications may be made and used only by the maker */
- /* of same, and not further distributed. Such modifications should */
- /* be mailed to the author for consideration for addition to the */
- /* software and incorporation in subsequent releases. */
- /* */
- /********************************************************************/
-
- #pragma csect(code, "GG@IERR ")
- #pragma csect(static,"GG$IERR ")
- #include "gg.h"
-
- /****** ISPF error handler. ******************************************/
-
- void
- GGierr(gp)
- RGGCB *gp;
- {
- char errbuf[] = "DISPLAY PANEL(ISPTERM)";
- int errlen;
-
- errlen = strlen(errbuf);
- if (ISPEXEC(&errlen,errbuf) > 8) {
- fprintf(stderr,
- "\n*** Severe ISPF error, cannot even display ISPTERM error panel.\n");
- fprintf(stderr,
- "\n*** Return code from ISPF service is %d\n",gp->ispfrc);
- return;
- }
- }
-
- ./ ADD NAME=GGIGET
-
- /********************************************************************/
- /* */
- /* Copyright (c) The Charles Stark Draper Laboratory, 1992, 1993 */
- /* GOPHER server due to Shawn Hart at the University of Delaware. */
- /* GOPHER client due to Steve Bacher at Draper Laboratory. */
- /* SAS modifications due to Dale Ingold at SAS Institute, Inc. */
- /* */
- /* This software is provided on an "AS IS" basis. All warranties, */
- /* including the implied warranties of merchantability and fitness, */
- /* are expressly denied. */
- /* */
- /* Provided this copyright notice is included, this software may */
- /* be freely distributed and not offered for sale. */
- /* */
- /* Changes or modifications may be made and used only by the maker */
- /* of same, and not further distributed. Such modifications should */
- /* be mailed to the author for consideration for addition to the */
- /* software and incorporation in subsequent releases. */
- /* */
- /********************************************************************/
-
- #pragma csect(code, "GG@IGET ")
- #pragma csect(static,"GG$IGET ")
- #include "gg.h"
-
- /****** Retrieve the value of an ISPF variable into an integer. ******/
-
- int
- GGiget(gp,varname)
- RGGCB *gp;
- char *varname;
- {
- char varbuf [16];
- int vcopy_length = 16;
-
- if (!strchr(varname,' ')) {
- fprintf(stderr,"GGiget: no blank passed in variable name %s\n",
- varname);
- return FALSE;
- }
-
- gp->ispfrc = ISPLINK("VCOPY",varname,&vcopy_length,varbuf,"MOVE");
- switch (gp->ispfrc) {
- case 0:
- varbuf[vcopy_length] = '\0';
- return atoi(varbuf);
- case 8:
- return 0;
- case 16:
- fprintf(stderr,
- "Error: ISPF variable buffer too short to get %s\n",
- varname);
- return 0;
- default:
- GGierr(gp); /* handle ISPF error */
- return 0;
- }
- }
-
- ./ ADD NAME=GGINFO
-
- /********************************************************************/
- /* */
- /* Copyright (c) The Charles Stark Draper Laboratory, 1992, 1993 */
- /* GOPHER server due to Shawn Hart at the University of Delaware. */
- /* GOPHER client due to Steve Bacher at Draper Laboratory. */
- /* SAS modifications due to Dale Ingold at SAS Institute, Inc. */
- /* */
- /* This software is provided on an "AS IS" basis. All warranties, */
- /* including the implied warranties of merchantability and fitness, */
- /* are expressly denied. */
- /* */
- /* Provided this copyright notice is included, this software may */
- /* be freely distributed and not offered for sale. */
- /* */
- /* Changes or modifications may be made and used only by the maker */
- /* of same, and not further distributed. Such modifications should */
- /* be mailed to the author for consideration for addition to the */
- /* software and incorporation in subsequent releases. */
- /* */
- /********************************************************************/
-
- #pragma csect(code, "GG@INFO ")
- #pragma csect(static,"GG$INFO ")
- #include "gg.h"
-
- /****** Gopher it. ***************************************************/
-
- Bool
- GGinfo(gp,ip)
- RGGCB *gp;
- RINFO *ip;
- {
- char buf [513];
-
- if (!ip) {
- ERR1("Info is not available - this is not a Gopher item.");
- return FALSE;
- }
-
- GGclrtx(gp,NULL);
-
- sprintf(buf,""); GGouttx(gp,buf,NULL,NO_VALUE);
- sprintf(buf,"Type=%c%c",
- ip->type,ip->plus); GGouttx(gp,buf,NULL,NO_VALUE);
- sprintf(buf,"Name=%s",ip->desc); GGouttx(gp,buf,NULL,NO_VALUE);
- sprintf(buf,"Path=%s",ip->path); GGouttx(gp,buf,NULL,NO_VALUE);
- sprintf(buf,"Host=%s",ip->host); GGouttx(gp,buf,NULL,NO_VALUE);
- sprintf(buf,"Port=%d",ip->port); GGouttx(gp,buf,NULL,NO_VALUE);
- sprintf(buf,"End"); GGouttx(gp,buf,NULL,NO_VALUE);
-
- return TRUE;
- }
-
- ./ ADD NAME=GGISPF
-
- /********************************************************************/
- /* */
- /* Copyright (c) The Charles Stark Draper Laboratory, 1992, 1993 */
- /* GOPHER server due to Shawn Hart at the University of Delaware. */
- /* GOPHER client due to Steve Bacher at Draper Laboratory. */
- /* SAS modifications due to Dale Ingold at SAS Institute, Inc. */
- /* */
- /* This software is provided on an "AS IS" basis. All warranties, */
- /* including the implied warranties of merchantability and fitness, */
- /* are expressly denied. */
- /* */
- /* Provided this copyright notice is included, this software may */
- /* be freely distributed and not offered for sale. */
- /* */
- /* Changes or modifications may be made and used only by the maker */
- /* of same, and not further distributed. Such modifications should */
- /* be mailed to the author for consideration for addition to the */
- /* software and incorporation in subsequent releases. */
- /* */
- /********************************************************************/
-
- #pragma csect(code, "GG@ISPF ")
- #pragma csect(static,"GG$ISPF ")
- #include "gg.h"
-
- /****** Call ISPF service. *******************************************/
-
- Bool
- GGispf(gp,ispfbuf)
- RGGCB *gp;
- char *ispfbuf;
- {
- int ispflen = strlen(ispfbuf);
-
- if (!gp) return TRUE;
-
- #ifndef ISPFV2
- if (gp->test_mode) {
- #endif
- if (ispflen >= 6 && (!memcmp(ispfbuf,"ADDPOP",6) ||
- !memcmp(ispfbuf,"REMPOP",6))) {
- gp->ispfrc = 0;
- return TRUE;
- }
- #ifndef ISPFV2
- }
- #endif
-
- gp->ispfrc = ISPEXEC(&ispflen,ispfbuf);
- if (gp->ispfrc > 8) {
-
- /* Ignore ADDPOP and REMPOP errors, especially if they are due to
- ISPF V3 not being active. */
-
- if (gp->ispfrc == 20 && !gp->debug_mode && ispflen >= 6 &&
- (!memcmp(ispfbuf,"ADDPOP",6) ||
- !memcmp(ispfbuf,"REMPOP",6))) return TRUE;
-
- GGierr(gp); /* handle ISPF error */
- return FALSE;
- }
- return TRUE;
- }
-
- ./ ADD NAME=GGIVGET
-
- /********************************************************************/
- /* */
- /* Copyright (c) The Charles Stark Draper Laboratory, 1992, 1993 */
- /* GOPHER server due to Shawn Hart at the University of Delaware. */
- /* GOPHER client due to Steve Bacher at Draper Laboratory. */
- /* SAS modifications due to Dale Ingold at SAS Institute, Inc. */
- /* */
- /* This software is provided on an "AS IS" basis. All warranties, */
- /* including the implied warranties of merchantability and fitness, */
- /* are expressly denied. */
- /* */
- /* Provided this copyright notice is included, this software may */
- /* be freely distributed and not offered for sale. */
- /* */
- /* Changes or modifications may be made and used only by the maker */
- /* of same, and not further distributed. Such modifications should */
- /* be mailed to the author for consideration for addition to the */
- /* software and incorporation in subsequent releases. */
- /* */
- /********************************************************************/
-
- #pragma csect(code, "GG@IVGET")
- #pragma csect(static,"GG$IVGET")
- #include "gg.h"
-
- /****** Retrieve the value of an ISPF variable. **********************/
-
- Bool
- GGivget(gp,varname,varbuf,varbuflen)
- RGGCB *gp;
- char *varname;
- char *varbuf;
- int varbuflen;
- {
- int vcopy_length;
-
- if (!strchr(varname,' ')) {
- fprintf(stderr,"GGivget: no blank passed in variable name %s\n",
- varname);
- return FALSE;
- }
-
- /*
- * If varbuflen is negative, that means that the value is not to be
- * treated as a C string, and the null character is not to be
- * appended to the resulting value. This is used for hex values
- * (like addresses) that are stored in ISPF table row variables.
- */
-
- if (varbuflen < 0) vcopy_length = -varbuflen;
- else vcopy_length = varbuflen;
-
- /* Note that on entry, vcopy_length is an integer that contains
- * the length of the buffer. On return it is updated to the length
- * of the value returned. Since we have to stick a null character
- * on the end of it for C, the actual buffer passed must be at least
- * one character longer than the length as defined to ISPF.
- */
-
- gp->ispfrc = ISPLINK("VCOPY",varname,&vcopy_length,varbuf,"MOVE");
- switch (gp->ispfrc) {
- case 0:
- if (varbuflen >= 0)
- varbuf[vcopy_length] = '\0';
- return TRUE;
- case 8:
- strcpy(varbuf,"");
- return TRUE;
- case 16:
- fprintf(stderr,
- "Error: ISPF variable buffer too short to get %s\n",
- varname);
- return FALSE;
- default:
- GGierr(gp); /* handle ISPF error */
- return FALSE;
- }
- }
-
- ./ ADD NAME=GGIVPUT
-
- /********************************************************************/
- /* */
- /* Copyright (c) The Charles Stark Draper Laboratory, 1992, 1993 */
- /* GOPHER server due to Shawn Hart at the University of Delaware. */
- /* GOPHER client due to Steve Bacher at Draper Laboratory. */
- /* SAS modifications due to Dale Ingold at SAS Institute, Inc. */
- /* */
- /* This software is provided on an "AS IS" basis. All warranties, */
- /* including the implied warranties of merchantability and fitness, */
- /* are expressly denied. */
- /* */
- /* Provided this copyright notice is included, this software may */
- /* be freely distributed and not offered for sale. */
- /* */
- /* Changes or modifications may be made and used only by the maker */
- /* of same, and not further distributed. Such modifications should */
- /* be mailed to the author for consideration for addition to the */
- /* software and incorporation in subsequent releases. */
- /* */
- /********************************************************************/
-
- #pragma csect(code, "GG@IVPUT")
- #pragma csect(static,"GG$IVPUT")
- #include "gg.h"
-
- /****** Set the value of an ISPF variable. ***************************/
-
- Bool
- GGivput(gp,varname,varbuf,varlen)
- RGGCB *gp;
- char *varname;
- char *varbuf;
- int varlen;
- {
- int vreplace_length = (varlen < 0 ? strlen(varbuf) : varlen);
-
- gp->ispfrc = ISPLINK("VREPLACE",varname,&vreplace_length,varbuf);
- switch (gp->ispfrc) {
- case 0:
- return TRUE;
- case 16:
- fprintf(stderr,
- "Error: ISPF variable buffer too short to put %s\n",
- varname);
- return FALSE;
- default:
- GGierr(gp); /* handle ISPF error */
- return FALSE;
- }
- }
-
- ./ ADD NAME=GGMENU
-
- /********************************************************************/
- /* */
- /* Copyright (c) The Charles Stark Draper Laboratory, 1992, 1993 */
- /* GOPHER server due to Shawn Hart at the University of Delaware. */
- /* GOPHER client due to Steve Bacher at Draper Laboratory. */
- /* SAS modifications due to Dale Ingold at SAS Institute, Inc. */
- /* */
- /* This software is provided on an "AS IS" basis. All warranties, */
- /* including the implied warranties of merchantability and fitness, */
- /* are expressly denied. */
- /* */
- /* Provided this copyright notice is included, this software may */
- /* be freely distributed and not offered for sale. */
- /* */
- /* Changes or modifications may be made and used only by the maker */
- /* of same, and not further distributed. Such modifications should */
- /* be mailed to the author for consideration for addition to the */
- /* software and incorporation in subsequent releases. */
- /* */
- /********************************************************************/
-
- #pragma csect(code, "GG@MENU ")
- #pragma csect(static,"GG$MENU ")
- #include "gg.h"
-
- /****** Display Gopher menu in data set. *****************************/
-
- Bool
- GGmenu(gp,pp)
- RGGCB *gp;
- char *pp;
- {
- GOPHERINFO *ip;
- GOPHERINFO *saveip;
- char *cp;
- Bool rc;
- char zprefix [9];
- char temp [129];
- char savebook [63];
-
- if (!*pp) {
- ERR1("You must supply a data set name for a Gopher menu.");
- return FALSE;
- }
-
- if (strlen(pp) >= sizeof(temp)) {
- ERR1("Gopher menu name too long");
- return FALSE;
- }
-
- GETMAIN(ip, struct gopherinfo, 1, "menu gopherinfo struct");
- if (!ip) {
- ERR2("Not enough memory to load Gopher menu %s",pp);
- return FALSE;
- }
-
- CLEAR(ip);
-
- copy_uppercase(temp,pp);
-
- if (temp[0] == '\'') {
- strcpy(ip->path, temp+1);
- cp = &ip->path[strlen(ip->path)-1];
- if (*cp == '\'') *cp = '\0';
- }
- else {
- VGET("ZPREFIX ",zprefix);
- if (!*zprefix) sprintf(ip->path,"'%s'",pp);
- else sprintf(ip->path,"%s.%s",zprefix,pp);
- }
-
- ip->type = GOPHER_MENU;
- sprintf(ip->desc,"User menu %s",ip->path);
- strcpy (ip->host, "-");
- ip->port = SERV_TCP_PORT;
- saveip = gp->ginfo;
- gp->ginfo = ip;
- strcpy(savebook,gp->current_bookmark_ds);
- strncpy(gp->current_bookmark_ds,ip->path,sizeof(savebook));
-
- rc = GGgofor(gp,ip,AS_NORMAL);
-
- gp->ginfo = saveip;
- strcpy(gp->current_bookmark_ds,savebook);
-
- FREEMAIN(ip,"menu gopherinfo struct");
-
- return rc;
- }
-
- ./ ADD NAME=GGMTFER
-
- /********************************************************************/
- /* */
- /* Copyright (c) The Charles Stark Draper Laboratory, 1992, 1993 */
- /* GOPHER server due to Shawn Hart at the University of Delaware. */
- /* GOPHER client due to Steve Bacher at Draper Laboratory. */
- /* SAS modifications due to Dale Ingold at SAS Institute, Inc. */
- /* */
- /* This software is provided on an "AS IS" basis. All warranties, */
- /* including the implied warranties of merchantability and fitness, */
- /* are expressly denied. */
- /* */
- /* Provided this copyright notice is included, this software may */
- /* be freely distributed and not offered for sale. */
- /* */
- /* Changes or modifications may be made and used only by the maker */
- /* of same, and not further distributed. Such modifications should */
- /* be mailed to the author for consideration for addition to the */
- /* software and incorporation in subsequent releases. */
- /* */
- /********************************************************************/
-
- #pragma csect(code, "GG@MTFER")
- #pragma csect(static,"GG$MTFER")
- #include "gg.h"
-
- /*********************************************************************/
-
- void
- GGmtfer(
- int rc,
- char *kind)
- {
- char *ermsg;
-
- switch (rc) {
- case MTF_OK:
- ermsg = NULL;
- break;
- case EINACTIVE:
- ermsg = "MTF is inactive";
- break;
- case ESUBCALL:
- ermsg = "The MTF call was issued from a subtask";
- break;
- case EWRONGOS:
- ermsg = "MTF is not supported under CMS, IMS, CICS, or DB2";
- break;
- case EACTIVE:
- ermsg = "MTF has already been initialized and is active";
- break;
- case ENAME2LNG:
- ermsg = "The parallel module name is longer than 8 characters";
- break;
- case ETASKNUM:
- ermsg = "The number of tasks specified is invalid";
- break;
- case ENOMEM:
- ermsg = "Insufficient storage for MTF internal areas";
- break;
- case EMODFIND:
- ermsg = "The parallel load module was not found";
- break;
- case EMODREAD:
- ermsg = "The parallel load module was not sucessfully read";
- break;
- case EMODFMT:
- ermsg = "The parallel load module format is invalid";
- break;
- case EAUTOALC:
- ermsg = "Automatic allocation of standard stream DD failed";
- break;
- case ETASKFAIL:
- ermsg = "The attempt to attach task(s) has failed";
- break;
- case ETASKABND:
- ermsg = "One or more subtasks have abnormally terminated";
- break;
- case EBADLNKG:
- ermsg = "TSCHED has been invoked via invalid linkage";
- break;
- case ETASKID:
- ermsg = "The task ID specified is not valid";
- break;
- case EENTRY:
- ermsg = "The parallel function was not in the parallel module";
- break;
- default:
- ermsg = "Unknown MTF error";
- break;
- }
-
- if (ermsg) {
- fprintf(stderr,"GGserve: %s error code %d:\n %s\n", kind, rc, ermsg);
- }
-
- return;
-
- }
-
- ./ ADD NAME=GGOUTS
-
- /********************************************************************/
- /* */
- /* Copyright (c) The Charles Stark Draper Laboratory, 1992, 1993 */
- /* GOPHER server due to Shawn Hart at the University of Delaware. */
- /* GOPHER client due to Steve Bacher at Draper Laboratory. */
- /* SAS modifications due to Dale Ingold at SAS Institute, Inc. */
- /* */
- /* This software is provided on an "AS IS" basis. All warranties, */
- /* including the implied warranties of merchantability and fitness, */
- /* are expressly denied. */
- /* */
- /* Provided this copyright notice is included, this software may */
- /* be freely distributed and not offered for sale. */
- /* */
- /* Changes or modifications may be made and used only by the maker */
- /* of same, and not further distributed. Such modifications should */
- /* be mailed to the author for consideration for addition to the */
- /* software and incorporation in subsequent releases. */
- /* */
- /********************************************************************/
-
- #pragma csect(code, "GG@OUTS")
- #pragma csect(static,"GG$OUTS")
-
- #include "gg.h"
-
- /*
- * This is a Gopher server routine that outputs data to a socket.
- * If the "socket" is actually a file pointer, then output is
- * written to the file pointer.
- *
- */
-
- /*=================================================================*/
-
- Bool
- GGouts(RRECV *R,
- char *text,
- int outlen)
- {
- char *outp;
- int len;
- int reallen;
- Bool rc;
- Bool binary;
- char outbuf [515]; /* hold an output character string */
-
- switch (R->pathtype) {
- case GOPHER_MAC_BINHEX:
- case GOPHER_DOS_BINARCH:
- case GOPHER_BINARY: binary = TRUE; break;
- default: binary = FALSE; break;
- }
-
- if (outlen == NO_VALUE) outlen = text ? strlen(text) : 0;
- else if (outlen == OUT_PLUS) {
- outlen = text ? strlen(text) : 0;
- binary = FALSE;
- if (!R->outfp)
- fprintf(stderr,"GGouts: %*.*s\n", outlen, outlen, text);
- }
- else binary = TRUE;
-
- if (R->outfp) { /* if using non-socket interface */
- if (text) {
- if (fwrite(text, sizeof(char), outlen, R->outfp) < 0) {
- fprintf(stderr,"Error writing to output file\n");
- return FALSE;
- }
- if (!binary) {
- if (fputc('\n',R->outfp) < 0) {
- fprintf(stderr,"Error writing to output file\n");
- return FALSE;
- }
- }
- }
- return TRUE;
- }
-
- if (binary) {
- if (!text) {
- outp = "";
- len = 0;
- }
- else {
- outp = text;
- len = outlen;
- }
- reallen = len;
- }
- else {
- outp = outbuf;
- if (!text) {
- outbuf[0] = '.';
- len = 1;
- }
- else {
- len = strlen(text);
- if (len >= sizeof(outbuf)-3) len = sizeof(outbuf)-3;
- if (text[0] == '.') {
- outbuf[0] = '.';
- memcpy(outbuf+1,text,len);
- len++;
- }
- else {
- memcpy(outbuf,text,len);
- }
- }
- outbuf[len ] = CARRIAGE_RETURN;
- outbuf[len+1] = LINE_FEED;
- outbuf[len+2] = '\0';
- reallen = len + 2;
-
- EBCDIC_TO_ASCII(outbuf,reallen);
-
- }
-
- rc = TRUE;
-
- if (R->outlen + reallen > sizeof(R->sockbuf)) {
-
- if (write(R->sockfd,R->sockbuf,R->outlen) < 0) {
- REPORT_TCP_ERROR("SEND");
- rc = FALSE;
- }
- R->outlen = 0;
- }
-
- memcpy(R->sockbuf + R->outlen, outp, reallen);
- R->outlen += reallen;
-
- if (!text) { /* flush socket */
- if (write(R->sockfd,R->sockbuf,R->outlen) < 0) {
- REPORT_TCP_ERROR("SEND");
- rc = FALSE;
- }
- }
- return rc;
- }
-
- ./ ADD NAME=GGOUTTX
-
- /********************************************************************/
- /* */
- /* Copyright (c) The Charles Stark Draper Laboratory, 1992, 1993 */
- /* GOPHER server due to Shawn Hart at the University of Delaware. */
- /* GOPHER client due to Steve Bacher at Draper Laboratory. */
- /* SAS modifications due to Dale Ingold at SAS Institute, Inc. */
- /* */
- /* This software is provided on an "AS IS" basis. All warranties, */
- /* including the implied warranties of merchantability and fitness, */
- /* are expressly denied. */
- /* */
- /* Provided this copyright notice is included, this software may */
- /* be freely distributed and not offered for sale. */
- /* */
- /* Changes or modifications may be made and used only by the maker */
- /* of same, and not further distributed. Such modifications should */
- /* be mailed to the author for consideration for addition to the */
- /* software and incorporation in subsequent releases. */
- /* */
- /********************************************************************/
-
- #pragma csect(code, "GG@OUTTX")
- #pragma csect(static,"GG$OUTTX")
- #include "gg.h"
-
- /****** Output a line of text retrieved from the server. *************/
-
- TEXTLINE *
- GGouttx(gp,line,ip,len)
- RGGCB *gp;
- char *line;
- RINFO *ip;
- int len;
- {
- TEXTHDR *thp;
- TEXTLINE *tp;
- short line_length;
- short total_text_length;
- short tab_expansion_length;
- Bool tabs_present;
- char *p;
- char *q;
- char *t;
- int e;
- int u;
-
- static char tab_expansion_buffer[8*TEXT_BYTES];
-
- thp = (ip ? &ip->thdr : &gp->thdr);
-
- /* If line starts with double period, make it a single period. */
-
- if (len != NO_VALUE) {
- line_length = len;
- tabs_present = FALSE;
- total_text_length = line_length + 1;
- }
- else {
-
- if (ip && !memcmp(line,"..",2)) line++;
-
- /* Add this line to the current queue of server text lines. */
- /* First, expand tabs in the line. */
-
- line_length = strlen(line);
- t = strchr(line,'\t');
- if (!t) {
- tabs_present = FALSE;
- total_text_length = line_length + 1;
- }
- else {
- tabs_present = TRUE;
- p = line;
- q = line + line_length;
- e = 0;
- memset(tab_expansion_buffer,' ',sizeof(tab_expansion_buffer));
- for (;;) {
- u = t - p;
- if (u > 0) {
- memcpy(tab_expansion_buffer+e,p,u);
- e += u;
- }
- if (t == q) break;
- e = e / 8 * 8 + 8;
- p = t+1;
- t = strchr(p,'\t');
- if (!t) t = q;
- }
- tab_expansion_length = e;
- tab_expansion_buffer[tab_expansion_length] = '\0';
- total_text_length = line_length + tab_expansion_length + 1;
- }
- }
-
- GETMAIN(tp, char, offsetof(struct textline, text) + total_text_length,
- "text line");
-
- if (!tp) {
- ERR1("There is not enough virtual storage to process server text.");
- return NULL;
- }
-
- tp->next = NULL;
- tp->text_length = line_length;
- memcpy(tp->text,line,line_length);
- tp->text[line_length] = '\0';
- if (tabs_present) {
- tp->tab_expanded_text_length = tab_expansion_length;
- tp->tab_expanded_text = tp->text + line_length;
- strcpy(tp->tab_expanded_text,tab_expansion_buffer);
- }
- else {
- tp->tab_expanded_text_length = line_length;
- tp->tab_expanded_text = tp->text;
- }
-
- if (!thp->last_text_line) {
- thp->first_text_line = tp;
- thp->text_body_line = tp;
- thp->current_text_line = tp;
- }
- else thp->last_text_line->next = tp;
-
- thp->last_text_line = tp;
- thp->text_line_count++;
-
- if (thp->text_max_length < tp->text_length)
- thp->text_max_length = tp->text_length;
- if (thp->text_max_tab_expanded_length < tp->tab_expanded_text_length)
- thp->text_max_tab_expanded_length = tp->tab_expanded_text_length;
-
- return tp;
-
- }
-
- ./ ADD NAME=GGPMSG
-
- /********************************************************************/
- /* */
- /* Copyright (c) The Charles Stark Draper Laboratory, 1992, 1993 */
- /* GOPHER server due to Shawn Hart at the University of Delaware. */
- /* GOPHER client due to Steve Bacher at Draper Laboratory. */
- /* SAS modifications due to Dale Ingold at SAS Institute, Inc. */
- /* */
- /* This software is provided on an "AS IS" basis. All warranties, */
- /* including the implied warranties of merchantability and fitness, */
- /* are expressly denied. */
- /* */
- /* Provided this copyright notice is included, this software may */
- /* be freely distributed and not offered for sale. */
- /* */
- /* Changes or modifications may be made and used only by the maker */
- /* of same, and not further distributed. Such modifications should */
- /* be mailed to the author for consideration for addition to the */
- /* software and incorporation in subsequent releases. */
- /* */
- /********************************************************************/
-
- #define SUPPRESS_V_DECLARATION
- #pragma csect(code, "GG@PMSG ")
- #pragma csect(static,"GG$PMSG ")
- #include "gg.h"
-
- /****** Set an ISPF message, or write to SYSOUT if batch mode. *******/
-
- void
- GGpmsg(gp,msgtype,msghelp,msgformat) /* also ... for sprintf args */
- RGGCB *gp;
- int msgtype;
- char *msghelp;
- char *msgformat;
- {
- va_list argp;
- char *cp;
- char zerrsm [25];
- char zerrhm [9];
- char zerralrm [4];
- char zerrlm [ZERRLM_SIZE];
- char buf [257];
-
- va_start(argp,msgformat);
- vsprintf(buf,msgformat,argp);
- va_end(argp);
-
- cp = strchr(buf,';');
- if (cp) {
- *cp = '\0';
- strncpy(zerrsm,buf, sizeof(zerrsm));
- strncpy(zerrlm,cp+1,sizeof(zerrlm));
- }
- else {
- strcpy(zerrsm,"");
- strncpy(zerrlm,buf,sizeof(zerrlm));
- }
-
- zerrsm[sizeof(zerrsm)-1] = '\0';
- zerrlm[sizeof(zerrlm)-1] = '\0';
-
- if (msghelp) strcpy(zerrhm, msghelp);
- else strcpy(zerrhm, "*" );
-
- switch (msgtype) {
- case NOTIFY_MSG: strcpy(zerralrm,"NO "); break;
- case WARNING_MSG:
- case CRITICAL_MSG:
- default: strcpy(zerralrm,"YES"); break;
- }
-
- VPUT("ZERRSM ", zerrsm);
- VPUT("ZERRLM ", zerrlm);
- VPUT("ZERRHM ", zerrhm);
- VPUT("ZERRALRM ",zerralrm);
-
- gp->setmsg = TRUE;
-
- return;
- }
-
- ./ ADD NAME=GGPROC
-
- /********************************************************************/
- /* */
- /* Copyright (c) The Charles Stark Draper Laboratory, 1992, 1993 */
- /* GOPHER server due to Shawn Hart at the University of Delaware. */
- /* GOPHER client due to Steve Bacher at Draper Laboratory. */
- /* SAS modifications due to Dale Ingold at SAS Institute, Inc. */
- /* */
- /* This software is provided on an "AS IS" basis. All warranties, */
- /* including the implied warranties of merchantability and fitness, */
- /* are expressly denied. */
- /* */
- /* Provided this copyright notice is included, this software may */
- /* be freely distributed and not offered for sale. */
- /* */
- /* Changes or modifications may be made and used only by the maker */
- /* of same, and not further distributed. Such modifications should */
- /* be mailed to the author for consideration for addition to the */
- /* software and incorporation in subsequent releases. */
- /* */
- /********************************************************************/
-
- #pragma csect(code, "GG@PROC")
- #pragma csect(static,"GG$PROC")
-
- #include "gg.h"
-
- /*=================================================================*/
-
- /****************************************************/
- /* This routine "cleans" a string by removing the */
- /* leading spaces and trailing spaces and non- */
- /* graphical characters. */
- /****************************************************/
-
- static char *
- trim_leading_and_trailing_space(char *string)
- {
- char *str;
-
- /* first clean up the beginning of the string... */
-
- str = skip_leading_space(string);
-
- /* now look at the end of the string... */
-
- strip_trailing_junk_in_place(str);
-
- return str;
- }
-
- /*=================================================================*/
-
- static void
- upcase_and_append_domain_name(RECV *R,
- char *hostname)
- {
- int hostlen;
- int domslen;
-
- if (EQUAL(hostname,LOCAL_HOST_FROB)) return;
-
- uppercase_in_place(hostname);
-
- #ifdef APPEND_DOMAIN_NAME_TO_SELF
- hostlen = strlen(hostname);
- domslen = strlen(R->mydomain);
- if (hostlen <= domslen ||
- memcmp(hostname+hostlen-domslen, R->mydomain, domslen)) {
- strncat(hostname, R->mydomain, domslen);
- }
- #endif
- return;
- }
-
- /*=================================================================*/
-
- static Bool
- insure_my_name(RECV *R)
- {
-
- /* Determine the local path name, if not already set. */
-
- if (!*R->myname) {
- if (gethostname(R->myname,MAXHOSTNAMELEN) < 0) {
- fprintf(stderr,"GOPHER:gethostname() failed, can't get my name\n");
- GGbarf(R,"Oops, the GOPHER server had an attack of amnesia");
- return FALSE;
- }
- upcase_and_append_domain_name(R,R->myname);
- }
-
- return TRUE;
-
- }
-
- /*=================================================================*/
-
- static void
- log_it(RRECV *R,
- char *resource,
- Bool rc)
- {
- int count = 0;
- char *type;
- struct tm *now;
- time_t ltime;
- char datestr [ 65];
- char temp [257];
- char wtotemp [513];
-
- /* The format of a gopher log entry, as generated by the mother of
- * all gophers, is:
- *
- * Mon Oct 11 14:07:05 1993 13780 support4 : retrieved file foo/bar
- *
- */
-
- if (R->outfp) return;
-
- if (!*resource) {
- if (rc) strcpy(temp,"Root Connection");
- else strcpy(temp,"error - Root Connection");
- }
- else {
- type = GGtype(R->pathtype);
- if (type[0] == ' ') type = "Comment";
- sprintf(temp,"%s %c%s %s",
- rc ? "retrieved" : "error - ",
- tolower(type[0]), type+1, resource);
- }
-
- time(<ime);
- now = localtime(<ime);
- strftime(datestr,sizeof(datestr)-1,"%a %b %d %H:%M:%S %Y",now);
-
- sprintf(wtotemp,"%s %s %d %s : %s",
- rc ? GOPHER_MSGID_OK : GOPHER_MSGID_ERROR,
- datestr,
- count,
- /* R->hostname, suppressed for privacy reasons */
- "{}",
- temp);
-
- GGwto(wtotemp);
-
- }
-
- /*=================================================================*/
-
- static Bool
- authorized_file(RRECV *R)
- {
- return GGacces(R,ACCESS_CHECK); /* uses R->fileptr as argument */
- }
-
- /*=================================================================*/
-
- /* Generic routine to begin getting data from a gopher resource. */
-
- static Bool
- gopher_open(RECV *R)
- {
- char *opentype;
-
- if (R->openfun) return (R->openfun)(R);
-
- if (R->binary) opentype = "rb";
- else opentype = "rb,type=record";
-
- if (!(R->readfile=fopen(R->buffer,opentype))) {
- perror(R->buffer);
- return FALSE;
- }
- return TRUE;
-
- }
-
- /*=================================================================*/
-
- /* Generic routine to stop getting data from a gopher resource. */
-
- static Bool
- gopher_close(RECV *R)
- {
-
- if (R->closefun) return (R->closefun)(R);
-
- if (!R->readfile) return FALSE;
- if (fclose(R->readfile) < 0) {
- fprintf(stderr,"GGproc: Error closing file %s\n",R->fileptr);
- return FALSE;
- }
- else return TRUE;
-
- }
-
- /*=================================================================*/
-
- /* Generic routine to get text data from a gopher resource. */
-
- static Bool
- gopher_read(RECV *R)
- {
- char *cp;
-
- if (R->readfun) return (R->readfun)(R);
-
- memset(R->buffer,0,RBUFSIZE);
-
- if (R->binary) {
- R->bytes_read = fread(R->buffer,sizeof(char),RBUFSIZE,R->readfile);
- }
- else {
- (void)fread(R->buffer,RBUFSIZE,1,R->readfile);
- }
- if (ferror(R->readfile)) {
- fprintf(stderr,"GGproc: gopher_read: Error reading file\n");
- R->readstatus = STATUS_ERROR;
- return FALSE;
- }
- else if (feof(R->readfile)) {
- R->readstatus = STATUS_EOF;
- return FALSE;
- }
- if (!R->binary) {
- if ((cp=strchr(R->buffer,'\n'))) *cp = '\0';
- strip_trailing_in_place(R->buffer);
- }
- R->readstatus = STATUS_OK;
- return TRUE;
-
- }
-
- /*=================================================================*/
-
- /*******************************************************************/
- /* This routine figures out what type of parm line */
- /* the current line is. We'll return the token */
- /* type to the caller. */
- /* */
- /* INPUT: buffer pointer to first line of file */
- /* (Note: string must be null terminated! */
- /* OUTPUT: Type of token. (See in include file...) */
- /*******************************************************************/
-
- static int
- menukeywd(char *buffer,
- char *token,
- char *operand)
- {
- char *cp;
- char *tokval;
- char *oprval;
- char *tokptr;
- char tokstr[256];
-
- strcpy(token,"");
- strcpy(operand,"");
- switch (buffer[0]) {
- case TOKCOMMENT1:
- case TOKCOMMENT2:
- case TOKCOMMENT3: return COMMENTTOK;
- }
- strcpy(tokstr,buffer);
- cp = strchr(tokstr,'=');
- if (cp) {
- *cp = '\0';
- strcpy(operand,cp+1);
- }
- tokptr = skip_leading_space(tokstr);
- uppercase_in_place(tokptr);
- strcpy(token,tokptr);
-
- /*********/
- /* now look at the tokens to see if we have a weener... */
- /*********/
-
- if(EQUAL(tokptr,TOKTYPE)) return(TYPETOK);
- if(EQUAL(tokptr,TOKNAME)) return(NAMETOK);
- if(EQUAL(tokptr,TOKPATH)) return(PATHTOK);
- if(EQUAL(tokptr,TOKHOST)) return(HOSTTOK);
- if(EQUAL(tokptr,TOKPORT)) return(PORTTOK);
- if(EQUAL(tokptr,TOKEND)) return(ENDTOK);
-
- /* for back compatibility with the old MVS GOPHER server */
-
- if(EQUAL(tokptr,TOKDISPLAY)) return(DISPLAYTOK);
- if(EQUAL(tokptr,TOKSELECT)) return(SELECTTOK);
- if(EQUAL(tokptr,TOKSELECT)) return(SELECTTOK);
-
- return(NULLTOK);
-
- }
-
- /*=================================================================*/
-
- /*******************************************************************/
- /* This routine sends a file to the calling client. */
- /* It assumes the file is a text formatted file. */
- /* INPUT: buffer pointer to the already read line... */
- /* readfile file we're going to read from.. */
- /* maxlen size of the buffer. */
- /* sockfd socket descriptor for client. */
- /* */
- /* OUTPUT: send the file to the client */
- /*******************************************************************/
- static void
- sendafile(RECV *R)
- {
-
- /*******/
- /* send the first line (cause we already read it) */
- /*******/
-
- if (!GGouts(R,R->buffer,NO_VALUE)) return;
-
- /*******/
- /* get the rest of the lines of the file and send them... */
- /*******/
-
- for (;;) {
- gopher_read(R);
- switch (R->readstatus) {
- case STATUS_ERROR:
- (void)GGouts(R,"<<<*** I/O ERROR ON MVS FILE ***>>>",NO_VALUE);
- return;
- case STATUS_EOF:
- break;
- default:
- if (!GGouts(R,R->buffer,NO_VALUE)) return;
- continue;
- }
- break;
- }
- }
-
- /*=================================================================*/
-
- static void
- senderrors(RECV *R)
- {
-
- for (;;) {
- gopher_read(R);
- switch (R->readstatus) {
- case STATUS_ERROR:
- (void)GGouts(R,"<<<*** I/O ERROR ON MVS FILE ***>>>",NO_VALUE);
- return;
- case STATUS_EOF:
- break;
- default:
- if (R->pathtype == GOPHER_MENU) GGbarf(R,R->buffer);
- else (void)GGouts(R,R->buffer,NO_VALUE);
- continue;
- }
- break;
- }
- }
-
- /*=================================================================*/
-
- /*******************************************************************/
- /* This routine formats a menu file into gopher data & sends it */
- /* to the client. */
- /* INPUT: buffer pointer to the already read line... */
- /* readfile file we're going to read from.. */
- /* maxlen size of the buffer. */
- /* sockfd socket descriptor for client */
- /* */
- /* OUTPUT: send the menu to the client */
- /*******************************************************************/
-
- #define MENU_STUFF_SIZE GOPHER_DESC_LENGTH + \
- GOPHER_PATH_LENGTH + \
- GOPHER_HOST_LENGTH + 20
-
- static void
- sendamenu(RECV *R)
- {
- char *operptr;
- char *tot; /*pointer for strtok */
- char *cp;
- int kindotoken;
- int i;
- char token [133];
- char operand [133];
- char outbuf [MENU_STUFF_SIZE];
- char uphost [GOPHER_HOST_LENGTH+1];
- MENUITEM menu;
-
- CLEAR(&menu);
- for (;;) {
- gopher_read(R);
- if (R->readstatus != STATUS_OK) break; /* error or end of file */
- if (!*R->buffer) continue;
- kindotoken = menukeywd(R->buffer,token,operand);
- switch(kindotoken) {
- case TYPETOK:
- operptr = skip_whitespace(operand);
- tot = strtok(operptr," ");
- i = strlen(tot);
- menu.gopherplus = '\0';
- if (i > 1) {
- cp = &tot[i-1];
- switch (*cp) {
- case '+': /* regular gopher+ item */
- case '?': /* ASK block item */
- menu.gopherplus = *cp;
- *cp = '\0';
- i--;
- break;
- default: break;
- }
- }
- if (i == 1) menu.type = *tot;
- else {
- uppercase_in_place(tot);
- if (EQUAL(tot,TYPEFILE)) menu.type = GOPHER_FILE;
- else if (EQUAL(tot,TYPEMENU)) menu.type = GOPHER_MENU;
- else if (EQUAL(tot,TYPECSO)) menu.type = GOPHER_CSO;
- else if (EQUAL(tot,TYPEINDEX)) menu.type = GOPHER_INDEX;
- else if (EQUAL(tot,TYPETELNET)) menu.type = GOPHER_TELNET;
- else if (EQUAL(tot,TYPETN3270)) menu.type = GOPHER_TN3270;
- else if (EQUAL(tot,TYPEBINARY)) menu.type = GOPHER_BINARY;
- else if (EQUAL(tot,TYPEWHOIS)) menu.type = GOPHER_WHOIS;
- else if (EQUAL(tot,TYPEBOOKMANAGER))
- menu.type = GOPHER_BOOKMANAGER;
- else menu.type = GOPHER_ERROR;
- }
- break;
- case NAMETOK:
- case DISPLAYTOK:
- strncpy(menu.desc, operand, sizeof(menu.desc));
- break;
- case PATHTOK:
- case SELECTTOK:
- operptr = skip_whitespace(operand);
- strncpy(menu.select, operptr, sizeof(menu.select));
- break;
- case HOSTTOK:
- *menu.hostname = '\0';
- if (EQUAL(operptr,IDENT_HOST_FROB)) { /* HOST=+ */
- strncpy(menu.hostname, R->myname, sizeof(menu.hostname));
- }
- else {
- operptr = skip_whitespace(operand);
- strncpy(menu.hostname, operptr, sizeof(menu.hostname));
- }
- strcpy(uphost, menu.hostname);
- upcase_and_append_domain_name(R,uphost);
-
- break;
- case PORTTOK:
- operptr = skip_whitespace(operand);
- if (EQUAL(operptr,IDENT_HOST_FROB)) /* PORT=+ */
- menu.port = R->myport;
- else menu.port = atoi(operptr);
- break;
- case ENDTOK:
- case COMMENTTOK:
- if (menu.port == 0) {
- switch (menu.type) {
- case GOPHER_TELNET: break;
- case GOPHER_TN3270: break;
- default: menu.port = GOPHER_PORT_NUMBER; break;
- }
- }
- /* If host is local and path is in the form "(member)",
- * and current dsname is a PDS, then use same PDS:
- * i.e. turn PATH=(FOOBAR) into PATH=AA.BB.CC(FOOBAR)
- */
- if (*R->myname
- && EQUAL(uphost, R->myname)
- && *menu.select == '(' /* ) */
- && (cp = strchr(R->dsname,'(' /* ) */ ))) {
- memcpy(outbuf, R->dsname, (cp-R->dsname));
- strcpy(outbuf+(cp-R->dsname), menu.select);
- strncpy(menu.select, outbuf, sizeof(menu.select));
- }
- if (menu.type && *menu.desc && *menu.hostname) {
- sprintf(outbuf,"%c%s\t%s\t%s\t%d%c%c",
- menu.type,menu.desc,
- menu.select,menu.hostname,menu.port,
- menu.gopherplus ? '\t' : '\0',
- menu.gopherplus);
- if (!GGouts(R,outbuf,NO_VALUE)) return;
- }
- fflush(stdout);
- CLEAR(&menu);
- break;
- default:
- break;
- }
- }
- }
-
- /*=================================================================*/
-
- /*******************************************************************/
- /* This routine determines what type of gopher file */
- /* we've opened. We'll return the file type to the */
- /* caller. */
- /* */
- /* INPUT: ident pointer to first line of file */
- /* */
- /* OUTPUT: MENU file type is a menu */
- /* FILE file type is a file */
- /* BINARY file type is binary */
- /* INDEX file type is an INDEX (not done) */
- /*******************************************************************/
-
- static char
- getftype(RECV *R)
- {
- char *bufptr;
- char buffer[RBUFSIZE];
-
- /* If a type was found in the path, use that type. */
-
- if (R->pathtype) return R->pathtype;
-
- /**********/
- /* else, convert the string to upper case... */
- /*********/
- copy_uppercase(buffer,R->buffer);
- bufptr = skip_leading_space(buffer);
-
- /**********/
- /* return the type of file. */
- /*********/
-
- if (EQUAL(bufptr,MENUIDENT)) R->pathtype = GOPHER_MENU;
- else if (EQUAL(bufptr,INDEXIDENT)) R->pathtype = GOPHER_INDEX;
- else /* dunno, assume it's file */ R->pathtype = GOPHER_FILE;
-
- return(R->pathtype);
-
- }
-
- /*=================================================================*/
-
- static Bool
- get_directory(RECV *R)
- {
- FILE *dirfile;
- char *cp;
- char *mp;
- int i;
- short block_count;
- short bump_amount;
- Bool reject;
- Bool no_more;
- char dirblk [256];
- char pdsspec [256];
- char entry [256];
-
- /* The local path name is required for this function. */
-
- if (!(dirfile=fopen(R->buffer,"rb,recfm=u,lrecl=256"))) {
- perror(R->buffer);
- printf("Can't open PDS directory:%s\n",R->dsname);
- GGbarf(R,"Sorry, the GOPHER server can't open the directory");
- return(FALSE);
- }
-
- while (!feof(dirfile)) {
-
- no_more = FALSE;
-
- do {
- memset(dirblk,0x00,256);
- fread(dirblk,256,1,dirfile);
- if (feof(dirfile)) break;
- if (ferror(dirfile)) {
- printf("Can't read PDS directory:%s\n", R->fileptr);
- GGbarf(R,"Sorry, the GOPHER server can't read the directory");
- fclose(dirfile);
- return FALSE;
- }
- mp = dirblk;
- block_count = *(short *)mp - 2; /* # bytes in dir block */
- mp += 2; /* addr of dir block data */
- while (block_count > 0) {
- if (!memcmp(mp,"\xff\xff\xff\xff\xff\xff\xff\xff",8)) break;
- reject = FALSE;
- /*
- * Uncomment this if you want to skip aliases.
- * It is recommended that you let aliases through, since
- * they often have better names (e.g. TSO HELP files)
- *
- * if ((mp[11] & 0x80) != 0) {
- * fprintf(stderr,"Skipping alias: %-8.8s\n",mp);
- * reject = TRUE;
- * }
- */
- if (!reject) {
- strcpy(pdsspec, R->dsname);
- cp = strchr(pdsspec, '\0');
- *(cp++) = '(';
- for (i = 0; i < 8 && mp[i] != ' '; cp++, i++) *cp = mp[i];
- *(cp++) = ')';
- *cp = '\0';
- sprintf(entry,"0%8.8s\t%s\t%s\t%d",
- mp, pdsspec, R->myname, SERV_TCP_PORT);
- (void)GGouts(R,entry,NO_VALUE);
- }
- bump_amount = 12 + ((mp[11] & 0x1f) * 2);
- mp += bump_amount;
- block_count -= bump_amount;
- }
- } while(!no_more);
- }
-
- fclose(dirfile);
- return TRUE;
- }
-
- /*=================================================================*/
-
- static Bool
- get_flat_file(RECV *R)
- {
-
- if (!gopher_open(R)) {
- printf("INVALID! requested:%s\n",R->fileptr);
- GGbarf(R,"Sorry, the GOPHER server couldn't open the file");
- return(FALSE);
- }
-
- /* A gopher+ client wants a success indication plus "-1", which
- means the following data is delivered in dot-stuffing mode. */
-
- if (R->gopherplus) {
- if (!GGouts(R,"+-1",OUT_PLUS)) return FALSE;
- }
-
- /************/
- /* get the first line and see what type of file we've got. */
- /************/
-
- gopher_read(R);
- if (R->readstatus == STATUS_OK) {
-
- /************/
- /* Now let's go do whatever we need to for this file type. */
- /************/
-
- switch (getftype(R)) {
-
- case GOPHER_MENU:
- sendamenu(R);
- break;
- case GOPHER_FILE:
- default:
- sendafile(R);
- break;
- }
-
- }
-
- if (!gopher_close(R)) {
- GGbarf(R,"Sorry, the GOPHER server couldn't close the file");
- return FALSE;
- }
-
- return TRUE;
-
- }
-
- /*=================================================================*/
-
- static Bool
- get_error_file(RECV *R)
- {
-
- if (!gopher_open(R)) {
- printf("INVALID! requested:%s\n",R->fileptr);
- GGbarf(R,"Sorry, the GOPHER server couldn't open the file");
- return(FALSE);
- }
-
- senderrors(R);
-
- if (!gopher_close(R)) {
- GGbarf(R,"Sorry, the GOPHER server couldn't close the file");
- return FALSE;
- }
-
- return TRUE;
-
- }
-
- /*=================================================================*/
-
- static Bool
- get_binary_file(RECV *R)
- {
-
- if (!gopher_open(R)) {
- printf("INVALID! requested:%s\n",R->fileptr);
- GGbarf(R,"Sorry, the GOPHER server couldn't open the binary file");
- return(FALSE);
- }
-
- /* A gopher+ client wants a success indication plus "-2", which
- means the following data is delivered in dump-till-close mode. */
-
- if (R->gopherplus) {
- if (!GGouts(R,"+-2",OUT_PLUS)) return FALSE;
- }
-
- for (;;) {
- gopher_read(R);
- if (R->bytes_read > 0) {
- if (!GGouts(R,R->buffer,R->bytes_read)) return FALSE;
- }
- switch (R->readstatus) {
- case STATUS_ERROR:
- (void)GGouts(R,"<<<*** I/O ERROR ON MVS FILE ***>>>",NO_VALUE);
- return FALSE;
- case STATUS_EOF:
- break;
- default:
- continue;
- }
- break;
- }
-
- if (!gopher_close(R)) {
- GGbarf(R,"Sorry, the GOPHER server couldn't close the file");
- return FALSE;
- }
-
- return TRUE;
-
- }
-
- /*=================================================================*/
-
- static Bool
- get_as_file(RECV *R)
- {
-
- switch (R->pathtype) {
- case GOPHER_MAC_BINHEX:
- case GOPHER_DOS_BINARCH:
- case GOPHER_IMAGE:
- case GOPHER_BINARY:
- case GOPHER_BOOKMANAGER:
- R->binary = TRUE;
- return get_binary_file(R);
- default:
- R->binary = FALSE;
- return get_flat_file(R);
- }
-
- }
-
- /*=================================================================*/
-
- static Bool
- get_exec_data(RECV *R)
- {
-
- GGCB *gp = NULL; /* for GETMAIN and FREEMAIN */
- char *command;
- char *commandargs;
- int rexxrc;
- int cmdlen;
- int scan_count;
- int i;
- Bool rc;
- char exectest[RBUFSIZE];
-
- /*
- * Menu item should look like this:
- *
- * exec:rexxname any args
- *
- * The exec should write output to SYSTSPRT. Normal TSO command
- * output will be captured by the SYSTSPRT allocation only if
- * the Gopher server is run as a batch job.
- *
- * If this was sent by the client with a type 7 or type w, then
- * additional args will appear at the end delimited by a space.
- */
-
- rc = TRUE;
- scan_count = 0;
-
- if (R->wargptr) {
- cmdlen = strlen(R->fileptr) + strlen(R->wargptr) + 4;
- GETMAIN(command, char, cmdlen, "REXX command buffer");
- if (!command) {
- printf("Cannot allocate %d bytes of memory for exec\n", cmdlen);
- GGbarf(R,"Oops, the GOPHER server ran out of memory");
- return FALSE;
- }
- else sprintf(command,"%s %s",R->fileptr,R->wargptr);
- }
- else {
- cmdlen = 0;
- command = R->fileptr;
- }
-
- *exectest = '\0';
- sscanf(command, "%s %n", exectest, &scan_count);
- if (strlen(exectest) > 8) {
- GGbarf(R,"Sorry, name of exec is too long");
- return FALSE;
- }
- commandargs = command + scan_count;
-
- if (rc) {
-
- rexxrc = GGrexx(R,exectest,commandargs);
-
- if (!R->outfp) printf("Return code from %s exec is %d\n",
- exectest, rexxrc);
-
- if (rexxrc != 0) {
- GGbarf(R,"Sorry, the Gopher server was unable to run the exec");
- rc = FALSE;
- }
- else {
- rc = get_as_file(R); /* Display what the exec wrote */
- }
-
- }
-
- if (cmdlen > 0) FREEMAIN(command, "REXX command buffer");
- return rc;
-
- }
-
- /*=================================================================*/
-
- static Bool
- get_ftp_data(RECV *R,
- GOPHERTYPE ftptype,
- char *resource,
- OSTYPE ftpos,
- char *ftpprefix
- )
- {
- /*
- * FTP hack. The syntax is:
- * ftp0:host:path
- * ftp0:host:user:path
- * ftp0:host:user:pass:path
- * ftp1:host
- * ftp1:host:path
- * ftp1:host:user:path
- * ftp1:host:user:pass:path
- *
- * ftpvm0:vmhost:disk/path
- * ftpvm1:vmhost:disk
- *
- * ftp0 means ftp a file.
- * ftp1 means ftp a directory.
- * Obviously, ftp0:host cannot exist, because that will always
- * look for a remote FTP directory.
- *
- * If path is omitted, then path is remote ftp current directory
- * If user is omitted, defaults to "anonymous".
- * If pass is omitted, defaults to "client@localhost.domain.qual"
- *
- * The syntax is defined to let path always be the last item
- * just in case the path name contains a colon.
- *
- * For backward compatibility for a very short time, the form
- * ftp:host(other stuff) will be permitted. When this is used,
- * due to the limitations of the Gopher protocol, the only way to
- * let the server know that a directory instead of a file is wanted
- * is to append "/" to the end of the path.
- *
- * And, of course, if the path is omitted then that's got to be a
- * directory request as well.
- *
- * Note for the FTP options
- * No authorized-file check is done, because we assume that
- * any file available via anonymous ftp is wide open to the
- * world to begin with. Besides, we can't possibly specify
- * every remote file in the entire universe, now, can we?
- */
-
- char *ftpword1;
- char *ftpword2;
- char *ftpword3;
- char *ftpword4;
- char *cp;
- GOPHERTYPE savetype;
- struct Ftp *F;
- Bool ftpok;
- IOMODE crmode;
- struct Ftp ftp;
- TEMPFILE outtemp;
- TEMPFILE errtemp;
-
- ftpok = FALSE;
- ftpword1 = R->fileptr;
- ftpword2 = "";
- ftpword3 = "";
- ftpword4 = "";
-
- F = &ftp;
- CLEAR(F);
-
- cp = strchr(ftpword1,':');
- if (cp) {
- *cp = '\0';
- ftpword2 = cp + 1;
- cp = strchr(ftpword2,':');
- if (cp) {
- *cp = '\0';
- ftpword3 = cp + 1;
- cp = strchr(ftpword3,':');
- if (cp) {
- *cp = '\0';
- ftpword4 = cp + 1;
- }
- }
- }
- strncpy(F->host, ftpword1, sizeof(F->host));
- if (*ftpword2) {
- if (*ftpword3) {
- if (*ftpword4) {
- strncpy(F->user, ftpword2, sizeof(F->user));
- strncpy(F->pass, ftpword3, sizeof(F->pass));
- strncpy(F->path, ftpword4, sizeof(F->path));
- }
- else {
- strncpy(F->user, ftpword2, sizeof(F->user));
- strncpy(F->path, ftpword3, sizeof(F->path));
- }
- }
- else {
- strncpy(F->path, ftpword2, sizeof(F->path));
- }
- }
-
- /* Set defaults for path, user and pass if omitted.
- * Note that the password is set to client@site. If the site is
- * the "local" frob, then set it to the domain name, minus the
- * initial dot that should be there if you configured your MVS
- * gopher properly.
- */
-
- if (!*F->path) strcpy(F->path,"/");
- if (!*F->user) strcpy(F->user,"anonymous");
- if (!*F->pass) {
-
- /* should this be foo.draper.com@mvs.draper.com
- * or gopher@foo.draper.com?
- *
- * sprintf(F->pass,"%s@%s",R->hostname,
- * EQUAL(R->myname,LOCAL_HOST_FROB) ? R->mydomain+1 : R->myname);
- * or
- * sprintf(F->pass,"gopher@%s",R->hostname);
- *
- */
-
- strcpy(F->pass,"gopher@");
-
- #ifdef BLAB_MACHINE_NAME_TO_THE_WORLD
-
- if (*R->hostname) strcat(F->pass,R->hostname);
- else if (EQUAL(R->myname,LOCAL_HOST_FROB))
- strcat(F->pass,R->mydomain+1);
- else strcat(F->pass,R->myname);
-
- #else
-
- strcat(F->pass,R->mydomain+1);
-
- #endif
-
- }
-
- F->os = ftpos;
- strcpy(F->ftphack, ftpprefix);
-
- switch (ftptype) {
- case GOPHER_UNKNOWN: /* compatibility mode */
- cp = F->path + strlen(F->path) - 1;
- if (*cp == '/') {
- *cp = '\0';
- F->type = GOPHER_DIRECTORY;
- }
- else F->type = GOPHER_FILE;
- crmode = CRLF;
- break;
- case GOPHER_MAC_BINHEX:
- case GOPHER_DOS_BINARCH:
- case GOPHER_IMAGE:
- case GOPHER_BINARY:
- case GOPHER_BOOKMANAGER:
- F->type = ftptype;
- crmode = RBIN;
- break;
- default:
- F->type = ftptype;
- crmode = CRLF;
- break;
- }
-
- R->pathtype = F->type;
-
- /* Set resource name for logging. This is to conform with the
- * UMn Gopher syntax and also to suppress usernames and passwords.
- */
-
- sprintf(resource,"ftp:%s@%s",F->host,F->path);
-
- /* Create temporary files for FTP output. */
-
- CLEAR(&outtemp);
- CLEAR(&errtemp);
- outtemp.crmode = crmode;
- errtemp.crmode = CRLF;
-
- F->outfp = GGtemp(R,&outtemp,TEMP_CREATE);
- F->errfp = GGtemp(R,&errtemp,TEMP_CREATE);
-
- if (!F->outfp || !F->errfp) {
- GGbarf(R,
- "Sorry, the GOPHER server couldn't service the remote FTP request");
- return FALSE;
- }
-
- if (!memcmp(ftpprefix,"FTPDEBUG",8)) F->verboseflag = TRUE;
-
- ftpok = GGftp(R,F);
-
- fflush(F->outfp);
- fflush(F->errfp);
-
- /* Close temporary files. */
-
- F->outfp = GGtemp(R,&outtemp,TEMP_CLOSE);
- F->errfp = GGtemp(R,&errtemp,TEMP_CLOSE);
-
- if (!F->outfp || !F->errfp) {
- GGbarf(R,
- "Sorry, the GOPHER server couldn't service the remote FTP request");
- return FALSE;
- }
-
-
- if (ftpok) {
- savetype = R->pathtype;
- if (R->pathtype == GOPHER_MENU) R->pathtype = GOPHER_UNKNOWN;
- strcpy(R->buffer, outtemp.dsname);
- ftpok = get_as_file(R);
- if (savetype != GOPHER_UNKNOWN) R->pathtype = savetype;
- }
- else {
- strcpy(R->buffer, errtemp.dsname);
- R->binary = FALSE;
- ftpok = get_error_file(R);
- }
-
- /* Remove temporary files. */
-
- F->outfp = GGtemp(R,&outtemp,TEMP_REMOVE);
- F->errfp = GGtemp(R,&errtemp,TEMP_REMOVE);
-
- if (!F->outfp || !F->errfp) {
- GGbarf(R,
- "Sorry, the GOPHER server couldn't service the remote FTP request");
- return FALSE;
- }
-
- return ftpok;
-
- }
-
- /*=================================================================*/
-
- static Bool
- get_info(RRECV *R,
- char *resource)
- {
- int hacksize; /* length of hack prefix before : */
- Bool rc; /* return value */
- DSTYPE dsntype; /* SEQ, PDS or UNK */
- char *p;
- char *q;
- char *colonptr;
- char ddname [ 9];
- char hackprefix[ 17];
-
- *ddname = '\0';
- *hackprefix = '\0';
-
- /*
- * Process special hacks here.
- *
- * For example, if the file name begins with "exec:", then
- * execute the specified REXX exec.
- *
- * Hackless names are processed as files. "dd:" is not a
- * special hack but the normal C/370 DDname reference.
- *
- */
-
- colonptr = strchr(R->fileptr,':');
- if (colonptr) {
- hacksize = colonptr - R->fileptr;
- if (hacksize > 0 && hacksize < sizeof(hackprefix)) {
- for (p = hackprefix, q = R->fileptr;
- hacksize > 0;
- p++, q++, hacksize--) *p = toupper(*q);
- *p = '\0';
- }
- }
-
- if (EQUAL(hackprefix,"EXEC")) {
- /*
- * REXX exec, which must reside in GGEXEC DD.
- */
- if (!authorized_file(R)) {
- GGbarf(R,"Sorry, the GOPHER server won't run the exec for you");
- rc = FALSE;
- }
- else {
- R->fileptr = colonptr + 1; /* point to exec itself */
- rc = get_exec_data(R);
- }
- }
- else
- if (EQUAL(hackprefix,"DD")) {
- /*
- * C/370 style ddname. Assume sequential file - cannot be a PDS
- * because I don't feel like trying to determine that right now.
- */
- if (!authorized_file(R)) {
- GGbarf(R,"Sorry, the GOPHER server won't read the DD for you");
- rc = FALSE;
- }
- else {
- strcpy(R->buffer,R->fileptr); /* still points to "DD:xxxxxxxx" */
- strcpy(R->dsname,R->buffer); /* needed for PATH=(member) check */
- dsntype = SEQ;
- rc = get_as_file(R);
- }
- }
- else
- if (strlen(hackprefix) == 4 && !memcmp(hackprefix,"FTP",3)) {
- R->fileptr = colonptr + 1; /* point to ftp locator */
- rc = get_ftp_data(R,hackprefix[3],resource,DEFAULT_OS,"FTP");
- }
- else
- if (strlen(hackprefix) == 9 && !memcmp(hackprefix,"FTPDEBUG",8)) {
- R->fileptr = colonptr + 1; /* point to ftp locator */
- rc = get_ftp_data(R,hackprefix[8],resource,DEFAULT_OS,"FTPDEBUG");
- }
- else
- if (strlen(hackprefix) == 6 && !memcmp(hackprefix,"FTPVM",5)) {
- R->fileptr = colonptr + 1; /* point to ftp locator */
- rc = get_ftp_data(R,hackprefix[5],resource,VM_OS,"FTPVM");
- }
- else {
- /* Regular file name without ":" hack, or with invalid ":" hack.
- * Check to see that the file name is on our "official" list.
- */
- if (!authorized_file(R)) {
- GGbarf(R,"Sorry, the GOPHER server won't let you see the file");
- rc = FALSE;
- }
- else {
-
- /* Dynamically allocate data set and use generated ddname.
- * Note that we have to allocate the data set name to a ddname and
- * then open the ddname to prevent C/370 from barfing on otherwise
- * valid data set names like those with hyphens in them. But this
- * also lets us determine if the data set is sequential or a PDS.
- */
- strcpy(R->dsname,R->fileptr);
- dsntype = GGalloc(R->dsname,ddname,UNK,0);
- sprintf(R->buffer,"DD:%s",ddname);
- switch (dsntype) {
- case SEQ: rc = get_as_file(R); break;
- case PDS: rc = get_directory(R); break;
- default:
- printf("INVALID! requested:%s\n",R->fileptr);
- GGbarf(R,
- "Sorry, the GOPHER server couldn't allocate the file");
- rc = FALSE;
- }
- }
- }
-
- GGunalc(ddname); /* free the ddname if set */
-
- return rc;
-
- }
-
- /*=================================================================*/
-
- static Bool
- get_the_info(RRECV *R, char *resource, char *plusptr)
- {
-
- if (EQUAL(plusptr,"+") || EQUAL(plusptr,"+0")) {
- return get_info(R,resource);
- }
- else {
- GGbarf(R,
- "Sorry, there is no gopher+ support available for this item.");
- return FALSE;
- }
- }
-
- /*=================================================================*/
-
- static Bool
- get_adm_info(RRECV *R, char *resource, char *plusptr)
- {
-
- GGbarf(R,
- "Sorry, there is no extended information available for this item.");
- return FALSE;
- }
-
- /*=================================================================*/
-
- static Bool
- get_dir_info(RRECV *R, char *resource, char *plusptr)
- {
-
- GGbarf(R,
- "Sorry, there is no extended information available for this menu.");
- return FALSE;
- }
-
- /*=================================================================*/
-
- /*******************************************************************/
- /* This routine Processes the file the user requested. */
- /* If it's a menu, we'll form a menu line, if it's a */
- /* file, we'll just send it as is. */
- /* */
- /* INPUT: filename pointer to the file name to open */
- /* sockfd socket descriptor for the client */
- /* */
- /* OUTPUT: print "gopher" lines. */
- /* TRUE - file printed ok. */
- /* FALSE - Error reading or writing */
- /*******************************************************************/
-
- Bool
- GGproc(RECV *R,
- int in_local_mode
- )
- {
- Bool rc; /* return value */
- char *tabptr;
- char *plusptr;
- char resource[RBUFSIZE+1];
-
- /************/
- /* First, strip off any "bad" characters from the arguments. */
- /************/
-
- /*
- * Break the argument up into one or two pieces delimited by tab.
- * Note that the tab is returned both by an index search item and
- * by a gopher+ item. We have to assume that a client capable of
- * returning gopher+ items will never return a search string that
- * begins with one of the gopher+ characters.
- */
-
- R->gopherplus = NULL;
-
- R->fileptr = R->buffer; /* filename passed in buffer */
-
- tabptr = strchr(R->fileptr,'\t');
- if (tabptr) {
- plusptr = tabptr + 1;
- switch (*plusptr) {
- case '+':
- case '!':
- case '$': R->gopherplus = (GOPHERPLUS *)R; /* temporary */
- break;
- default: break;
- }
- *tabptr = '\0';
- R->fileptr = trim_leading_and_trailing_space(R->fileptr);
- R->wargptr = trim_leading_and_trailing_space(tabptr+1);
- }
- else {
- R->fileptr = trim_leading_and_trailing_space(R->fileptr);
- R->wargptr = NULL;
- }
-
- strncpy(resource,R->fileptr,sizeof(resource)-1);
-
- if (!*R->fileptr) {
- R->fileptr = DEFAULT_DIRECTORY;
- }
-
- /* If the *second* character of the path name is a "/", then
- * the first character is a gopher type.
- * If the first character of the path name is a "/", then
- * strip it off and punt with the rest of the file name.
- * If the first character is numeric, assume it's a gopher type.
- * Use the rest of the file name.
- * Otherwise, punt with the entire file name.
- */
-
- R->pathtype = '\0';
-
- if (strlen(R->fileptr) >= 2 && R->fileptr[1] == '/') {
- R->pathtype = R->fileptr[0];
- R->fileptr += 2;
- }
- else if (R->fileptr[0] == '/') {
- R->fileptr++;
- }
- else {
- switch (*R->fileptr) {
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9': R->pathtype = R->fileptr[0]; R->fileptr++; break;
- default: break;
- }
- }
-
- if (!R->outfp) printf("%s: requested:%s;\n",R->hostname,R->fileptr);
-
- (void)insure_my_name(R); /* get host name now before we need it */
-
- if (R->gopherplus) {
- if (!R->outfp)
- printf("Responding to %s request for gopher+ %s<tab>%s\n",
- R->hostname,R->fileptr,plusptr);
- switch (*plusptr) {
- case '+': rc = get_the_info(R,resource,plusptr); break;
- case '!': rc = get_adm_info(R,resource,plusptr); break;
- case '$': rc = get_dir_info(R,resource,plusptr); break;
- default: GGbarf(R,"Error, bad Gopher+ request");
- rc = FALSE; break;
- }
- }
- else rc = get_info(R,resource);
-
- if (!rc) {
- fflush(stdout);
- fflush(stderr);
- }
-
- if (!in_local_mode) {
- (void)GGouts(R,NULL,NO_VALUE); /* send terminating dot */
- }
-
- #ifdef LOG_GOPHER_ACCESSES
-
- log_it(R,resource,rc);
-
- #endif
-
- return rc;
-
- }
-
- ./ ADD NAME=GGREXX
-
- /********************************************************************/
- /* */
- /* Copyright (c) The Charles Stark Draper Laboratory, 1992, 1993 */
- /* GOPHER server due to Shawn Hart at the University of Delaware. */
- /* GOPHER client due to Steve Bacher at Draper Laboratory. */
- /* SAS modifications due to Dale Ingold at SAS Institute, Inc. */
- /* */
- /* This software is provided on an "AS IS" basis. All warranties, */
- /* including the implied warranties of merchantability and fitness, */
- /* are expressly denied. */
- /* */
- /* Provided this copyright notice is included, this software may */
- /* be freely distributed and not offered for sale. */
- /* */
- /* Changes or modifications may be made and used only by the maker */
- /* of same, and not further distributed. Such modifications should */
- /* be mailed to the author for consideration for addition to the */
- /* software and incorporation in subsequent releases. */
- /* */
- /********************************************************************/
-
- #pragma csect(code, "GG@REXX")
- #pragma csect(static,"GG$REXX")
-
- #include "gg.h"
- #include "ggrx.h"
-
- #define NUMBER_OF_REXX_ARGS 2
- #define DIE \
- GGbarf(R,"Sorry, the GOPHER server had a problem with the exec");\
- rexxrc = 999
-
- /*===================================================================*/
-
- /* Function invoked by gopher-close in GGproc. */
-
- static void
- rexx_close(RECV *R)
- {
- GGCB *gp = NULL; /* for GETMAIN and FREEMAIN */
-
- GGtemp(R,R->temp,TEMP_CLOSE);
- GGtemp(R,R->temp,TEMP_REMOVE);
- FREEMAIN(R->temp, "REXX temp file struct");
- R->temp = NULL;
-
- return;
- }
-
- /*===================================================================*/
-
- static void
- load_function(Rexxfun *rfunp,
- char *function_name)
- {
-
- if (!*rfunp) {
- (*rfunp) = (Rexxfun)fetch(function_name);
- if (!*rfunp) fprintf(stderr,"Cannot fetch %s\n",function_name);
- }
-
- return;
- }
-
- /*===================================================================*/
-
- static void
- unload_function(Rexxfun *rfunp)
- {
-
- if (*rfunp) {
- release((void (*)())(*rfunp));
- (*rfunp) = (Rexxfun)0;
- }
-
- return;
- }
-
- /*===================================================================*/
-
- int
- GGrexx(RECV *R,
- char *exectest,
- char *commandargs
- )
- {
- GGCB *gp = NULL; /* for GETMAIN and FREEMAIN */
- unsigned int bitflags;
- int rexxrc = 0;
- int irxexecrc;
- int i;
- Rexxfun irxexec;
- FILE *fp;
- char gopherargs[257];
- PARAMETER parameter[11];
- struct execblock execblk;
- struct {
- struct {
- char *argstring_ptr;
- int argstring_length;
- } argstring[NUMBER_OF_REXX_ARGS];
- int argstring_end;
- } arguments;
-
- GETMAIN(R->temp, struct tempfile, 1, "REXX temp file struct");
- if (!R->temp) {
- fprintf(stderr,"Cannot get a temp file struct\n");
- DIE;
- }
-
- irxexec = NULL;
-
- load_function(&irxexec,"IRXEXEC");
- if (!irxexec) {
- DIE;
- }
-
- /* old interface: allocate SYSTSPRT, run the exec, expecting it to
- * write to SYSTSPRT, then specify on return that the file SYSTSPRT
- * is to be read to get the gopher output.
- */
-
- /* new interface: allocate a new file, run the exec, expecting it
- * to write to that file, then specify on return that the file
- * is to be read to get the gopher output.
- */
-
- /* newer interface: run the exec, expecting it
- * to queue data to the data stack, then take each line on the
- * data stack and GGouts() it. On return, no file.
- */
-
- /* Give the exec an empty SYSTSPRT file to write into.
- * Then when we read it we can see only what was added.
- * Since IRXEXEC doesn't close SYSTSPRT, we can't remove it
- * and reallocate it.
- */
-
- /* Create a temporary file. */
-
- CLEAR(R->temp);
- R->temp->crmode = CRLF; /* for now, just assume non-binary */
-
- fp = GGtemp(R,R->temp,TEMP_CREATE);
-
- if (!fp) {
- printf("Cannot make a temporary file for REXX exec\n");
- DIE;
- }
-
- /* Open for write + close = clear it out */
-
- else if (fclose(fp) < 0) {
- printf("Cannot close temporary file for REXX exec\n");
- DIE;
- }
-
- if (rexxrc != 0) return rexxrc;
-
- /* Set up parameters for IRXEXEC:
- *
- * Param 1 - address of EXECBLK
- * Param 2 - address of arguments
- * Param 3 - bitflags
- * Param 4 - address of INSTBLK
- * Param 5 - address of CPPL
- * Param 6 - address of EVALBLOCK
- * Param 7 - address of 8-byte work area
- * Param 8 - address of user field
- * Param 9 - address of environment block
- * Param 10 - return code
- */
-
- /* set up exec block */
-
- CLEAR(&execblk);
- execblk.length = sizeof(execblk);
- memcpy (execblk.acryn, "IRXEXECB", 8);
- strncpy(execblk.member,exectest,8);
- for (i=0;i<8;i++) {
- if (execblk.member[i] == '\0')
- execblk.member[i] = ' ';
- }
- /* We may have just clobbered this, so do this after... */
-
- memcpy (execblk.ddname, REXX_EXEC_LIBRARY_DDNAME, 8);
- memcpy (execblk.subcom, REXX_EXEC_SUBCOM, 8);
-
- /* set up arguments */
-
- sprintf(gopherargs,"OUTDD=%s;HOST=%s;PORT=%d;CLIENT=%s",
- R->temp->ddname+3,
- R->myname,
- R->myport,
- R->hostname);
-
- arguments.argstring[0].argstring_ptr = commandargs;
- arguments.argstring[0].argstring_length = strlen(commandargs);
- arguments.argstring[1].argstring_ptr = gopherargs;
- arguments.argstring[1].argstring_length = strlen(gopherargs);
- arguments.argstring_end = 0xffffffff;
-
- /* Invoke the rexx exec */
-
- bitflags = (unsigned int)(INVOKE_EXEC_AS_COMMAND +
- RETURN_EXTENDED_RETURN_CODES);
-
- parameter[ 1] = (PARAMETER)&execblk;
- parameter[ 2] = (PARAMETER)&arguments;
- parameter[ 3] = (PARAMETER)bitflags;
- parameter[ 4] = (PARAMETER)NULL; /* no INSTBLK */
- parameter[ 5] = (PARAMETER)NULL; /* no CPPL */
- parameter[ 6] = (PARAMETER)NULL; /* no eval block */
- parameter[ 7] = (PARAMETER)NULL; /* no work area */
- parameter[ 8] = (PARAMETER)NULL; /* no user field, last parm */
- parameter[ 9] = (PARAMETER)NULL; /* no environment block */
- parameter[10] = (PARAMETER)0; /* return code */
-
- if (!R->outfp) {
- printf("Executing:%s %s\n", exectest, commandargs);
- printf("Gopherargs:%s\n",gopherargs);
- }
-
- irxexecrc = (*irxexec) (
- ¶meter[1],
- ¶meter[2],
- ¶meter[3],
- ¶meter[4],
- ¶meter[5],
- ¶meter[6],
- ¶meter[7],
- LASTPARM(¶meter[8]), /* old REXX */
- ¶meter[9],
- LASTPARM(¶meter[10]) /* new REXX */
- );
-
- if (irxexecrc != 0) {
- fprintf(stderr,"Return code from IRXEXEC is %d\n", irxexecrc);
- rexxrc = irxexecrc;
- }
- else {
- rexxrc = parameter[10];
- strcpy(R->buffer,R->temp->ddname);
- R->fileptr = R->buffer; /* Prepare for get-as-file */
- R->openfun = NULL;
- R->readfun = NULL;
- R->closefun = rexx_close;
- }
-
- unload_function(&irxexec);
-
- return rexxrc;
-
- }
-
- ./ ADD NAME=GGSERVE
-
- /********************************************************************/
- /* */
- /* Copyright (c) The Charles Stark Draper Laboratory, 1992, 1993 */
- /* GOPHER server due to Shawn Hart at the University of Delaware. */
- /* GOPHER client due to Steve Bacher at Draper Laboratory. */
- /* SAS modifications due to Dale Ingold at SAS Institute, Inc. */
- /* */
- /* This software is provided on an "AS IS" basis. All warranties, */
- /* including the implied warranties of merchantability and fitness, */
- /* are expressly denied. */
- /* */
- /* Provided this copyright notice is included, this software may */
- /* be freely distributed and not offered for sale. */
- /* */
- /* Changes or modifications may be made and used only by the maker */
- /* of same, and not further distributed. Such modifications should */
- /* be mailed to the author for consideration for addition to the */
- /* software and incorporation in subsequent releases. */
- /* */
- /********************************************************************/
-
- /*
- ***********************************************************************
- * *
- * GOPHER server, based on the simple TCP/IP server from Shawn Hart at *
- * the University of Delaware. *
- * *
- ***********************************************************************
- *
- * This server follows the GOPHER protocols defined by UMN.
- * For more information, see the ANONYMOUS FTP site at
- * BOOMBOX.MICRO.UMN.EDU.
- *
- ***********************************************************************
- *
- * November 1992 - parameters may be passed to the server:
- *
- * -d run in debug mode
- *
- ***********************************************************************
- *
- * December 1992 - support for SNS/TCPAccess compilation
- *
- ***********************************************************************
- */
-
- #pragma csect(code, "GG@SERVE")
- #pragma csect(static,"GG$SERVE")
- #include "gg.h"
-
- /********************************************************************/
-
- static int
- tcpsetup(int port,
- int qlen,
- int mtftasks,
- FILE *debugfp)
- {
- int tinitrc; /* loop counter*/
- int sockfd; /* loop counter*/
- int x; /* loop counter*/
- struct linger l; /* linger for setsockopt */
- struct sockaddr_in server; /*server address information */
-
- /* initialize the MTF environment. */
-
- if (debugfp) {
- fprintf(debugfp,"tinit...\n");
- fflush(debugfp);
- }
-
- tinitrc = tinit("GGSTASK", mtftasks);
-
- if (tinitrc != MTF_OK) {
- GGmtfer(tinitrc, "TINIT");
- return -1;
- }
-
- /* open a TCP socket... */
-
- if (debugfp) {
- fprintf(debugfp,"socket...\n");
- fflush(debugfp);
- }
-
- if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
- REPORT_TCP_ERROR("SOCKET - ");
- return -1;
- };
-
- /* set the linger option on so we wait for data to be sent... */
-
- l.l_onoff = 1;
- l.l_linger =100; /* wait 100 seconds before giving up */
-
- if (debugfp) {
- fprintf(debugfp,"setsockopt (%d, SO_LINGER)...\n",sockfd);
- fflush(debugfp);
- }
-
- if (setsockopt(sockfd,SOL_SOCKET,SO_LINGER,(char *)&l,sizeof(l))
- < 0) {
- REPORT_TCP_ERROR("SETSOCKOPT - ");
- return -1;
- }
-
- /* now bind our local address so that the client can send to us */
-
- memset((char *)&server, 0, sizeof(server));
- server.sin_family = AF_INET;
- server.sin_addr.s_addr = INADDR_ANY;
- server.sin_port = htons(port);
-
- if (debugfp) {
- fprintf(debugfp,"bind (%d)...\n",sockfd);
- fflush(debugfp);
- }
-
- if (Bind(sockfd, &server, sizeof(server)) < 0) {
- REPORT_TCP_ERROR("BIND - ");
- return -1;
- }
-
- /* now set length of the connection queue... */
-
- if (debugfp) {
- fprintf(debugfp,"listen (sockfd=%d, qlen=%d)...\n",sockfd,qlen);
- fflush(debugfp);
- }
-
- if (listen(sockfd,qlen) != 0) {
- REPORT_TCP_ERROR("LISTEN -");
- return -1;
- }
-
- return sockfd;
-
- }
-
-
- /********************************************************************/
- /*
- * This routine waits for an exception on the socket. When one
- * occurs (by a subtask's "TAKESOCKET"!) we'll close our (the main
- * task's) connection to it.
- *
- * INPUT s pointer to socket descripter.
- * OUTPUT rc -1 = connection timed out...
- * 0 = an excption occured!
- */
- /********************************************************************/
-
- #ifdef SNSTCPIP
-
- static int
- closesock(int newsockfd,
- int timeout,
- FILE *debugfp)
- {
- if (debugfp) {
- fprintf(debugfp,"close (%d)...\n",newsockfd);
- fflush(debugfp);
- }
-
- if (close(newsockfd) < 0) REPORT_TCP_ERROR("CLOSE -");
- return 0;
- }
-
- #else
-
- static int
- closesock(int newsockfd,
- int timeout,
- FILE *debugfp)
- {
- int temps;
- struct sockaddr clientaddress;
- int addrlen;
- int maxfdpl;
- struct fd_set readmask;
- struct fd_set writmask;
- struct fd_set exepmask;
- int rc;
- struct timeval time;
-
- temps = newsockfd;
- time.tv_sec = timeout;
- time.tv_usec = 0;
- maxfdpl = temps + 1;
-
- FD_ZERO(&readmask);
- FD_ZERO(&writmask);
- FD_ZERO(&exepmask);
- FD_SET(temps, &exepmask);
-
- if (debugfp) {
- fprintf(debugfp,"select (maxfdpl=%d)...\n",maxfdpl);
- fflush(debugfp);
- }
-
- rc = select(maxfdpl, &readmask, &writmask, &exepmask, &time);
-
- if (rc < 0) {
- REPORT_TCP_ERROR("SELECT - ");
- return rc;
- }
- else {
- if (rc == 0) fprintf(stdout,"The GIVESOCKET timed out!\n");
-
- if (debugfp) {
- fprintf(debugfp,"close (%d)...\n",newsockfd);
- fflush(debugfp);
- }
-
- if (close(newsockfd) < 0) REPORT_TCP_ERROR("CLOSE -");
- return rc;
- }
- }
-
- #endif
-
- /********************************************************************/
- /*
- * This routine starts a subtask, passing control of a socket
- * to it. It then waits for the subtask to take the socket and
- * then closes the socket.
- *
- * INPUT: newsockfd - socket descriptor to give to subtask.
- */
- /********************************************************************/
-
- static Bool
- spawn(
- int newsockfd,
- int timeout,
- RECV *recvp,
- FILE *debugfp)
- {
- int tschedrc;
- #ifdef SNSTCPIP
- unsigned long token;
- #else
- struct clientid clid;
- char mysname[8];
- #endif
-
- if (debugfp) {
- fprintf(debugfp,"getclientid...\n");
- fflush(debugfp);
- }
-
- #ifdef SNSTCPIP
-
- token = closepass(newsockfd);
- if (debugfp) {
- fprintf(debugfp,"token = %X\n",token);
- fflush(debugfp);
- }
-
- #else
-
- memset(&clid,0,sizeof(clid));
- if(getclientid(AF_INET,&clid) < 0) {
- REPORT_TCP_ERROR("GETCLIENTID");
- return FALSE;
- }
-
- if (debugfp) {
- fprintf(debugfp,"client name = %8.8s, subtaskname = %8.8s\n",
- clid.name, clid.subtaskname);
- fflush(debugfp);
- }
-
- clid.domain = AF_INET;
- memcpy(mysname,clid.subtaskname,8);
- memcpy(clid.subtaskname," ",8);
-
- if (debugfp) {
- fprintf(debugfp,"givesocket (%d)...\n",newsockfd);
- fflush(debugfp);
- }
-
- if(givesocket(newsockfd,&clid) != 0) {
- REPORT_TCP_ERROR("GIVESOCKET");
- return FALSE;
- }
- memcpy(clid.subtaskname,mysname,8);
-
- if (debugfp) {
- fprintf(debugfp,"client name = %8.8s, subtaskname = %8.8s\n",
- clid.name, clid.subtaskname);
- fflush(debugfp);
- }
-
- #endif
-
- if (debugfp) {
- fprintf(debugfp,"tsched...\n");
- fflush(debugfp);
- }
-
- tschedrc = tsched(MTF_ANY,"GGSRECV",
- #ifdef SNSTCPIP
- token,
- #else
- newsockfd,
- clid,
- #endif
- recvp,
- (debugfp ? 1 : 0));
-
- if (debugfp) {
- fprintf(debugfp,"tsched completed...rc=%d\n",tschedrc);
- fflush(debugfp);
- }
-
- if (tschedrc != 0) {
- GGmtfer(tschedrc,"TSCHED");
- return FALSE;
- }
-
- if (closesock(newsockfd,timeout,debugfp) < 0) {
- REPORT_TCP_ERROR("close socket");
- return FALSE;
- }
-
- return TRUE;
-
- }
-
- /******************************************************************/
-
- static Bool
- numparm(
- char *pvar,
- char *pval,
- int *ivalp
- )
- {
- if (*(pval + strspn(pval,"0123456789"))) {
- fprintf(stdout,"Non-numeric value given for %s: %s\n",
- pvar, pval);
- return FALSE;
- }
- else {
- *ivalp = atoi(pval);
- return TRUE;
- }
- }
-
- /******************************************************************/
-
- int
- main(int argc,
- char **argv)
- {
- int trc; /* return code */
- int x; /* loop counter*/
- int sockfd; /* connection socket...*/
- int newsockfd; /* new connection socket...*/
- int clientlen; /* new connection socket...*/
- int i;
- int n;
- int ival;
- char cval;
- char *p;
- char *cp;
- FILE *debugfp;
- FILE *pfp;
- struct sockaddr_in client; /* client address information */
- #ifndef SNSTCPIP
- struct clientid clid; /* client info for givesocket */
- #endif
- RECV recvtemplate;
- int mtftasks;
- int port;
- int qlength;
- int timeout;
- char telnet [257];
- char bookmgr [257];
- char domain [257];
- char pline [RBUFSIZE];
- char pvar [RBUFSIZE];
- char pval [RBUFSIZE];
- char buffer [255]; /* buffer for input/output*/
-
- /******************************************************************/
- /* Set parameter defaults. */
- /******************************************************************/
-
- mtftasks = MTF_TASKS;
- port = SERV_TCP_PORT;
- qlength = TCP_QUEUE_LENGTH;
- timeout = CONNECT_TIME_OUT;
- COPY(telnet, TELNET_COMMAND_NAME);
- COPY(bookmgr, BOOKMGR_COMMAND_NAME);
- COPY(domain, MY_DOMAIN_SUFFIX);
-
- /******************************************************************/
- /* Process server parameters. */
- /******************************************************************/
-
- debugfp = NULL;
-
- for (i = 1; i < argc; i++) {
- p = argv[i];
- if (*p == '-') {
- while (*++p) {
- switch (toupper(*p)) {
- case 'D': debugfp = fopen(DEBUG_FILE,"w");
- break;
- default: break;
- }
- }
- }
- }
-
- /******************************************************************/
- /* Read startup parameters from parameter file. */
- /******************************************************************/
-
- /*
- * If dd:GGPARMS is present, then read parameters therefrom.
- * If not, then use defaults. In any case, defaults will be
- * assigned where a corresponding parameter file line isn't found,
- *
- * Syntax of parameter file lines:
- *
- * VARIABLE value comments
- *
- * e.g.
- *
- * MTFTASKS 8 the number of tasks
- *
- * Comments are indicated by "!" in col 1.
- *
- */
-
- pfp = fopen(PARAMETER_FILE,"r");
- if (!pfp) {
- perror(PARAMETER_FILE);
- fprintf(stdout,
- "No parameter file. Using all installed defaults.\n");
- fflush(stderr);
- }
- else {
- for (;;) {
- fgets(pline, sizeof(pline), pfp);
- if (ferror(pfp)) {
- fprintf(stderr,"Error reading parameters from %s\n",
- PARAMETER_FILE);
- fflush(stderr);
- break;
- }
- if (feof(pfp)) break;
- cp = pline; /* Start parameter scan */
- if (*cp == '!') continue; /* Skip comment */
- *pvar = '\0'; /* Clear parameter variable */
- sscanf(cp,"%s %n",pvar,&n); /* Get parameter, bump scan */
- if (!*pvar) continue; /* If nothing on line, skip */
- uppercase_in_place(pvar); /* Fold variable name */
- cp += n; /* Bump to next word in file */
- *pval = '\0'; /* Clear parameter value */
- sscanf(cp,"%s %n",pval,&n); /* Get next word, bump scan */
- if (!*pval) {
- fprintf(stdout,"Parameter error: value missing for %s\n",
- pvar);
- continue;
- }
- fprintf(stderr,"Setting %s to '%s' (%d)\n",pvar,pval,ival);
- if (EQUAL(pvar,"MTFTASKS" )) {
- if (numparm(pvar,pval,&ival))
- mtftasks = ival;
- }
- else if (EQUAL(pvar,"PORT" )) {
- if (numparm(pvar,pval,&ival))
- port = ival;
- }
- else if (EQUAL(pvar,"QLENGTH" )) {
- if (numparm(pvar,pval,&ival))
- qlength = ival;
- }
- else if (EQUAL(pvar,"TIMEOUT" )) {
- if (numparm(pvar,pval,&ival))
- timeout = ival;
- }
- else if (EQUAL(pvar,"TELNET" )) {
- uppercase_in_place(pval);
- COPY(telnet,pval);
- }
- else if (EQUAL(pvar,"BOOKMGR" )) {
- uppercase_in_place(pval);
- COPY(bookmgr,pval);
- }
- else if (EQUAL(pvar,"DOMAIN" )) {
- uppercase_in_place(pval);
- COPY(domain,pval);
- }
- else {
- fprintf(stdout,"Unknown parameter, %s. Skipping.\n",pvar);
- }
- }
- (void)fclose(pfp);
- }
-
- /******************************************************************/
- /* display parameter values in effect */
- /******************************************************************/
-
- /* Set defaults to pass to the subtask. */
-
- CLEAR(&recvtemplate);
-
- recvtemplate.myport = port;
- recvtemplate.mytelnet = telnet;
- recvtemplate.mybkmgr = bookmgr;
- recvtemplate.mydomain = domain;
- recvtemplate.accvector = NULL; /* set when access table loaded */
-
- fprintf(stdout,"Parameter values in effect:\n\n");
- fprintf(stdout,"MTFTASKS = %d\n", mtftasks);
- fprintf(stdout,"QLENGTH = %d\n", qlength);
- fprintf(stdout,"TIMEOUT = %d\n", timeout);
- fprintf(stdout,"PORT = %d\n", recvtemplate.myport);
- fprintf(stdout,"TELNET = %s\n", recvtemplate.mytelnet);
- fprintf(stdout,"BOOKMGR = %s\n", recvtemplate.mybkmgr);
- fprintf(stdout,"DOMAIN = %s\n", recvtemplate.mydomain);
- fprintf(stdout,"\n");
-
- fflush(stdout);
-
- /******************************************************************/
- /* load the access table */
- /******************************************************************/
-
- if (!GGacces(&recvtemplate,ACCESS_LOAD)) {
- fprintf(stdout,"Could not load the access table!\n");
- exit(16);
- }
-
- /******************************************************************/
- /* set up the connection to the socket... */
- /******************************************************************/
-
- sockfd = tcpsetup(port,qlength,mtftasks,debugfp);
- if (sockfd < 0) {
- fprintf(stdout,"Could not set up the TCP/IP environment!\n");
- exit(16);
- }
-
- /******************************************************************/
- /* Now loop, waiting for a connection request. */
- /******************************************************************/
-
- clientlen = sizeof(client);
- x = 0;
- for (;;) {
-
- if (debugfp) {
- fprintf(debugfp,"accept (%d)...\n",sockfd);
- fflush(debugfp);
- }
-
- if ((newsockfd=Accept(sockfd,&client,&clientlen)) == -1) {
- REPORT_TCP_ERROR("ACCEPT - ");
- exit(8);
- }
- if (debugfp) {
- fprintf(debugfp,"newsockfd=%d...\n",newsockfd);
- fflush(debugfp);
- }
-
- x++;
- if (!spawn(newsockfd,timeout,&recvtemplate,debugfp)) {
- fprintf(stdout,"spawn failed for socket %d\n",newsockfd);
- exit(8);
- }
- else {
- if (debugfp) {
- fprintf(debugfp,"spawn OK for socket %d\n",newsockfd);
- fflush(debugfp);
- }
- }
- }
-
- /******************************************************************/
- /* Wait for all pending tasks to complete (should never */
- /* run, since I haven't added PURGE support yet...) */
- /* then shut down subtasks. */
- /******************************************************************/
-
- if (debugfp) {
- fprintf(debugfp,"tsyncro...\n");
- fflush(debugfp);
- }
-
- trc = tsyncro(MTF_ALL);
- if (trc != 0) {
- GGmtfer(trc,"TSYNCRO");
- }
-
- if (debugfp) {
- fprintf(debugfp,"tterm...\n");
- fflush(debugfp);
- }
-
- trc = tterm();
- if (trc != 4) {
- GGmtfer(trc,"TTERM");
- exit(8);
- }
-
- (void)GGacces(&recvtemplate,ACCESS_FREE); /* free access table */
-
- if (debugfp) fclose(debugfp);
-
- exit(0);
-
- }
- ./ ADD NAME=GGSLEEP
-
- /********************************************************************/
- /* */
- /* Copyright (c) The Charles Stark Draper Laboratory, 1992, 1993 */
- /* */
- /* This software is provided on an "AS IS" basis. All warranties, */
- /* including the implied warranties of merchantability and fitness, */
- /* are expressly denied. */
- /* */
- /* Provided this copyright notice is included, this software may */
- /* be freely distributed and not offered for sale. */
- /* */
- /* Changes or modifications may be made and used only by the maker */
- /* of same, and not further distributed. Such modifications should */
- /* be mailed to the author for consideration for addition to the */
- /* software and incorporation in subsequent releases. */
- /* */
- /********************************************************************/
-
- #pragma csect(code, "GG@SLEEP")
- #pragma csect(static,"GG$SLEEP")
-
- #include "gg.h"
- #include "ggsvc.h"
-
- #define STIMER_SVC 47
-
- int
- GGsleep(int seconds)
- {
- int hundredths_of_a_second;
- SVC_REGISTER reg15;
- SVC_REGISTER reg0;
- SVC_REGISTER reg1;
-
- hundredths_of_a_second = seconds * 100;
-
- reg15 = (SVC_REGISTER) 0;
- reg0 = (SVC_REGISTER) 0x91000000;
- reg1 = (SVC_REGISTER) &hundredths_of_a_second;
-
- SVC(STIMER_SVC,®15,®0,®1);
-
- return (int)reg15;
-
- }
-
- ./ ADD NAME=GGSOCKT
-
- /********************************************************************/
- /* */
- /* Copyright (c) The Charles Stark Draper Laboratory, 1992, 1993 */
- /* GOPHER server due to Shawn Hart at the University of Delaware. */
- /* GOPHER client due to Steve Bacher at Draper Laboratory. */
- /* SAS modifications due to Dale Ingold at SAS Institute, Inc. */
- /* */
- /* This software is provided on an "AS IS" basis. All warranties, */
- /* including the implied warranties of merchantability and fitness, */
- /* are expressly denied. */
- /* */
- /* Provided this copyright notice is included, this software may */
- /* be freely distributed and not offered for sale. */
- /* */
- /* Changes or modifications may be made and used only by the maker */
- /* of same, and not further distributed. Such modifications should */
- /* be mailed to the author for consideration for addition to the */
- /* software and incorporation in subsequent releases. */
- /* */
- /********************************************************************/
-
- #pragma csect(code, "GG@SOCKT")
- #pragma csect(static,"GG$SOCKT")
- #include "gg.h"
-
- /****** Output one data line for the server. *************************/
-
- Bool
- GGsockt(gp,sp)
- RGGCB *gp;
- RCONN *sp;
- {
- RECV *R;
- char *s_buf;
- int gopher_bytes;
- int writrc;
- Bool procok;
-
- /* Before sending a request to the server, do a cleanup operation
- * to make sure that no more responses are coming from the server.
- * This is done by GGservr here, but it is now done outside so that
- * the FTP gateway can call this routine without linkind it in.
- *
- * GGesrvr(gp,sp); -- End server read --
- *
- */
-
- /* If local mode, call server subtask processor with command. */
-
- if (gp && (R=gp->recvp) && !sp->is_ftp) {
- if (!R->outfp) {
- CRIT1("Can't send data locally, non-socket not connected");
- return FALSE;
- }
- strncpy(R->buffer, gp->gopher_command, sizeof(R->buffer)-1);
- strcpy(R->myname, LOCAL_HOST_FROB); /* used by PDS feature */
-
- /* allocate SYSTSPRT file, used by REXX EXEC interface */
-
- if (GGtso(
- "ALLOC FI(SYSTSPRT) T SP(100 100) REL REU DEL"
- " RECFM(V B) LRECL(1024) BLKSIZE(32760)"
- ) != 0) {
- fprintf(stderr,
- "Warning: Cannot allocate temporary SYSTSPRT file.\n");
- fprintf(stderr,
- " Some interfaces may not work properly.\n");
- }
-
- procok = GGproc(R,TRUE);
-
- /* free SYSTSPRT file, used by REXX EXEC interface */
-
- (void)GGunalc("SYSTSPRT");
-
- /* Prepare to read from the beginning of the file */
-
- if (fseek(R->outfp, 0, SEEK_SET) != 0) {
- CRIT1("Can't reposition to start of local file");
- return FALSE;
- }
- return TRUE; /* used to return procok but want to see barfs */
- }
-
- if (gp) {
- gopher_bytes = strlen(gp->gopher_command);
- memcpy(sp->client_buf,gp->gopher_command,gopher_bytes);
- }
- else {
- gopher_bytes = strlen(sp->client_buf);
- }
-
- sp->client_buf[gopher_bytes] = CARRIAGE_RETURN;
- sp->client_buf[gopher_bytes+1] = LINE_FEED;
-
- if (!sp->is_ftp &&
- sp->receiving_text &&
- gopher_bytes == 1 &&
- sp->client_buf[0] == '.') {
- sp->receiving_text = FALSE;
- }
-
- if (gp && gp->debug_mode)
- GGdump(gp,"Writing to server",sp->client_buf,gopher_bytes+2);
-
- EBCDIC_TO_ASCII(sp->client_buf,gopher_bytes+2);
-
- writrc = write(sp->ns, sp->client_buf, gopher_bytes+2);
- if (writrc < 0) {
- sp->connection_broken = TRUE;
- if (gp) {
- CRIT2("TCP/IP error: write() failed to send data to server %s.",
- gp->ggserver);
- }
- else {
- fprintf(stderr,
- "TCP/IP error: write() failed to send data to server %s.",
- sp->server_hostname);
- }
- return FALSE;
- }
-
- if (sp->is_ftp) return TRUE;
-
- /* Prepare server for read. */
-
- sp->server_has_nothing = FALSE;
- sp->server_finished_replying = FALSE;
- sp->sending_text = FALSE;
- sp->dont_read = FALSE;
-
- ISPF("CONTROL DISPLAY LOCK");
- ISPF("DISPLAY PANEL(GGMLSOCK)");
-
- return TRUE;
- }
-
- ./ ADD NAME=GGSOPT
-
- /********************************************************************/
- /* */
- /* Copyright (c) The Charles Stark Draper Laboratory, 1992, 1993 */
- /* GOPHER server due to Shawn Hart at the University of Delaware. */
- /* GOPHER client due to Steve Bacher at Draper Laboratory. */
- /* SAS modifications due to Dale Ingold at SAS Institute, Inc. */
- /* */
- /* This software is provided on an "AS IS" basis. All warranties, */
- /* including the implied warranties of merchantability and fitness, */
- /* are expressly denied. */
- /* */
- /* Provided this copyright notice is included, this software may */
- /* be freely distributed and not offered for sale. */
- /* */
- /* Changes or modifications may be made and used only by the maker */
- /* of same, and not further distributed. Such modifications should */
- /* be mailed to the author for consideration for addition to the */
- /* software and incorporation in subsequent releases. */
- /* */
- /********************************************************************/
-
- #pragma csect(code, "GG@SOPT ")
- #pragma csect(static,"GG$SOPT ")
- #include "gg.h"
-
- #define BOOLOPTSET(A,B,C) \
- switch (A[0]) { \
- case 'n': \
- case 'N': B = FALSE; break; \
- case 'y': \
- case 'Y': B = TRUE; break; \
- case '\0': \
- default: B = C; break; \
- }
-
- /****** Set options that are stored in ISPF profile. *****************/
-
- void
- GGsopt(gp,which)
- RGGCB *gp;
- OPTION which;
- {
- int arrows;
- char ggextpow [ 4];
- char ggextpap [ 4];
- char ggscroll [ 4];
- char ggcursor [ 4];
-
- if (which == OPTION_ALL) {
- ISPF("VGET (GGEXTPOW GGEXTPAP GGSCROLL GGCURSOR) PROFILE");
- }
-
- if (which == OPTION_ALL || which == OPTION_OTHER) {
- VGET("GGEXTPOW ", ggextpow);
- VGET("GGEXTPAP ", ggextpap);
- BOOLOPTSET(ggextpow, gp->warn_overwrite, TRUE);
- BOOLOPTSET(ggextpap, gp->warn_append, TRUE);
- }
-
- if (which == OPTION_ALL || which == OPTION_VIEW) {
- VGET("GGSCROLL ", ggscroll);
- VGET("GGCURSOR ", ggcursor);
- BOOLOPTSET(ggscroll, gp->autoscroll, TRUE);
- BOOLOPTSET(ggcursor, gp->autocursor, FALSE);
- }
-
- return;
- }
-
- ./ ADD NAME=GGSTASK
-
- /********************************************************************/
- /* */
- /* Copyright (c) The Charles Stark Draper Laboratory, 1992, 1993 */
- /* GOPHER server due to Shawn Hart at the University of Delaware. */
- /* GOPHER client due to Steve Bacher at Draper Laboratory. */
- /* SAS modifications due to Dale Ingold at SAS Institute, Inc. */
- /* */
- /* This software is provided on an "AS IS" basis. All warranties, */
- /* including the implied warranties of merchantability and fitness, */
- /* are expressly denied. */
- /* */
- /* Provided this copyright notice is included, this software may */
- /* be freely distributed and not offered for sale. */
- /* */
- /* Changes or modifications may be made and used only by the maker */
- /* of same, and not further distributed. Such modifications should */
- /* be mailed to the author for consideration for addition to the */
- /* software and incorporation in subsequent releases. */
- /* */
- /********************************************************************/
-
- #pragma csect(code, "GGSTASK ")
- #pragma csect(static,"GG$TASK ")
- #include "gg.h"
-
- /*=================================================================*/
-
- /*******************************************************************/
- /* */
- /* this is a debugging routine; it looks at the status of a */
- /* socket. */
- /*******************************************************************/
-
- static void
- lookatsocket(int sockfd)
- {
- int rc; /* return code */
- int length; /* length variable */
- int option;
- int x;
- struct linger l; /* linger structure */
- char buffer[RBUFSIZE];
-
- length = sizeof(l);
- if (Getsockopt(sockfd,SOL_SOCKET, SO_LINGER,&l,&length)==0) {
- printf("l_onoff=%d\n",l.l_onoff);
- printf("l_linger=%d\n",l.l_linger);
- }
- else REPORT_TCP_ERROR("GETSOCKOPT");
-
- length = sizeof(option);
- if (Getsockopt(sockfd,SOL_SOCKET, SO_ERROR,&option,&length)==0) {
- printf("so_error=%d\n",option);
- }
- else REPORT_TCP_ERROR("GETSOCKOPT");
-
- if (fcntl(sockfd,F_SETFL,FNDELAY)!=0) REPORT_TCP_ERROR("FCNTL");
-
- length = recv(sockfd,buffer,sizeof(buffer)-1,0);
- if (length == -1) {
- if (errno != EWOULDBLOCK) REPORT_TCP_ERROR("recv");
- }
- else {
- buffer[sizeof(buffer)-1] = 0;
- printf("buffer =%s\n",buffer);
- for (x=0;x<length;x++) printf("%x ",buffer[x]);
- printf("\n");
- }
-
- }
-
- /*******************************************************************/
-
- /**************************************************************/
- /* this routine processes the data once a connection */
- /* has been accepted. It just takes the data sent by the */
- /* client and prints it to sysprint, then sends it back */
- /* to the client. */
- /* */
- /* INPUT: newsockfd - socket descriptor */
- /* clid - takesocket structure... */
- /**************************************************************/
-
- void
- GGSrecv(
- #ifdef SNSTCPIP
- unsigned long token,
- #else
- int newsockfd,
- struct clientid clid,
- #endif
- RECV *recvtp,
- int is_debug
- )
- {
- RECV *R;
- struct hostent *hostentp;
- char *bufptr; /* pointer into buffer strings */
- char *cp;
- char *hp;
- char **halias;
- struct tm *tmp;
- int retcode; /* return code */
- int len; /* length of the buffer we're sent */
- int addrlen; /* length of client address socket */
- int hostlen;
- int domslen;
- int buflen;
- time_t timeval;
- struct sockaddr_in clientaddress; /* address of client */
- RECV r;
- char outbuf[RBUFSIZE]; /* hold an output string */
- char echobuf[RBUFSIZE];
- char timestamp[20];
-
- /* Initialize recv struct with values passed from main task. */
-
- R = &r;
- memcpy(R, recvtp, sizeof(RECV));
-
- #ifdef SNSTCPIP
-
- if (is_debug) {
- fprintf(stdout,"openold (token=%X)...\n",token);
- fflush(stdout);
- }
- s0skcfg.exitfunc = NULL; /* Set exit address to NULL */
- R->sockfd = openold(token);
- if (is_debug) {
- fprintf(stdout,"sockfd from openold is %d\n", R->sockfd);
- fflush(stdout);
- }
- if(R->sockfd < 0) {
- REPORT_TCP_ERROR("OPENOLD");
- fflush(stderr);
- return;
- }
-
- #else
-
- if (is_debug) {
- fprintf(stdout,"takesocket (newsockfd=%d)...\n",newsockfd);
- fprintf(stdout,"name is %8.8s, subtaskname is %8.8s\n",
- clid.name,clid.subtaskname);
- fflush(stdout);
- }
-
- R->sockfd = takesocket(&clid,newsockfd);
- if (is_debug) {
- fprintf(stdout,"sockfd from takesocket is %d\n", R->sockfd);
- fflush(stdout);
- }
- if(R->sockfd < 0) {
- REPORT_TCP_ERROR("TAKESOCKET");
- return;
- }
-
- #endif
-
- time(&timeval);
- tmp = localtime(&timeval);
- sprintf(timestamp,"%2.2d/%2.2d/%2.2d %2.2d:%2.2d:%2.2d",
- tmp->tm_mon + 1, tmp->tm_mday, tmp->tm_year,
- tmp->tm_hour, tmp->tm_min, tmp->tm_sec);
-
- if (is_debug) {
- fprintf(stdout,"getpeername...\n");
- fflush(stdout);
- }
-
- addrlen = sizeof(clientaddress);
- if(Getpeername(R->sockfd,&clientaddress,&addrlen)!=0) {
- REPORT_TCP_ERROR("GETPEERNAME");
- printf("could not determine client address for socket %d\n",
- R->sockfd);
- }
-
- /* Try to get the name of the client host.
- * First initialize the hostname to a printable representation of
- * the IP address in case we can't get a hostname.
- * We use curlies instead of the traditional squares because of
- * the ancient 3270's that will be displaying this stuff.
- */
-
- strcpy(R->hostname,"{");
- SPRINTF_IP_ADDRESS(R->hostname+1, clientaddress.sin_addr);
- strcat(R->hostname,"}");
-
- if (is_debug) {
- fprintf(stdout,"gethostbyaddr...\n");
- fflush(stdout);
- }
-
- hostentp = Gethostbyaddr(&clientaddress.sin_addr,
- sizeof(clientaddress.sin_addr),
- AF_INET);
-
- if (hostentp && hostentp->h_name) {
- memcpy(&R->clienthostent, hostentp, sizeof(struct hostent));
- strcpy(R->hostname,hostentp->h_name);
- uppercase_in_place(R->hostname);
- }
-
- strcpy(R->hosttest,R->hostname);
-
- hostlen = strlen(R->hosttest);
- domslen = strlen(R->mydomain);
- if (hostlen > domslen) {
- hp = R->hosttest + hostlen - domslen;
- if (!memcmp(hp, R->mydomain, domslen)) *hp = '\0';
- }
-
- printf("%s Connection from %s (%s, aka %s). Socket %d\n",
- timestamp,
- inet_ntoa(clientaddress.sin_addr), R->hostname, R->hosttest,
- R->sockfd);
-
- R->buffer[0] = '\0';
- bufptr = R->buffer;
-
- /***********************/
- /* NOTE: sometimes, if timing is right, RECV can return a 0 length */
- /* record when a connection is closed by the client!! below is a */
- /* hack to check for a 0 length record, and then terminate this */
- /* connection if we got one. */
- /***********************/
-
- #define RECV_SIZE (sizeof(R->buffer)-1)
-
- for (;;) {
- if (is_debug) {
- fprintf(stdout,"recv (sock=%d,size=%d)...\n",R->sockfd,RECV_SIZE);
- fflush(stdout);
- }
- if ((len=recv(R->sockfd,outbuf,RECV_SIZE,0)) <= 0) {
- REPORT_TCP_ERROR("RECV - ");
- printf("%s tcp error! len=%d\n",R->hostname, len);
- break;
- }
- *(outbuf+(len))=0; /*make sure it's null terminated...*/
- ASCII_TO_EBCDIC(outbuf,len);
- if (is_debug) {
- int i;
- fprintf(stdout,"recv length = %d\n",len);
- for (i=0;i<len;i++) {
- if (isprint(outbuf[i])) fprintf(stdout,"%c",outbuf[i]);
- else fprintf(stdout,"<0x%2.2x>",outbuf[i]);
- }
- fprintf(stdout,"\n");
- fflush(stdout);
- }
- if (strlen(R->buffer) + strlen(outbuf) >= sizeof(R->buffer)) {
- fprintf(stderr, "\nError: More than %d bytes seen without CRLF\n",
- RECV_SIZE);
- len = 0;
- break;
- }
- strcat(R->buffer,outbuf);
- bufptr=R->buffer+(strlen(R->buffer)-2);
- if (*bufptr == CARRIAGE_RETURN && *(bufptr+1) == LINE_FEED) break;
- /* hack for broken Mac Mosaic client */
- if (*bufptr == LINE_FEED && *(bufptr+1) == CARRIAGE_RETURN) break;
- }
-
- if (len < 0) {
- fprintf(stderr,"%s %s Error reading %s\n",timestamp,R->hostname);
- }
- else if (len == 0) {
- fprintf(stderr,"%s %s Null input from %s\n",timestamp,R->hostname);
- }
- else {
- strcpy(echobuf,R->buffer);
- buflen = strlen(echobuf);
- if (buflen == 0) *echobuf = '\n';
- else if (buflen == 1) {
- cp = echobuf;
- if (*cp == CARRIAGE_RETURN || *cp == LINE_FEED) *cp = '\n';
- }
- else {
- cp = echobuf + buflen - 2;
- if (*cp == CARRIAGE_RETURN && *(cp+1) == LINE_FEED) {
- *cp = '\n';
- *(cp+1) = '\0';
- }
- else {
- cp++;
- if (*cp == CARRIAGE_RETURN || *cp == LINE_FEED) *cp = '\n';
- }
- }
- fprintf(stderr,"%s %s Client data:%s",
- timestamp,R->hostname,echobuf);
- (void)GGproc(R,FALSE);
- }
-
- fflush(stdout);
- fflush(stderr);
-
- #ifdef DEBUGMTF
- lookatsocket(R->sockfd);
- #endif
-
- if (is_debug) {
- fprintf(stdout,"close (%d)...\n",R->sockfd);
- fflush(stdout);
- }
-
- if(close(R->sockfd)<0) REPORT_TCP_ERROR("CLOSE - ");
-
- }
- ./ ADD NAME=GGTEMP
-
- /********************************************************************/
- /* */
- /* Copyright (c) The Charles Stark Draper Laboratory, 1992, 1993 */
- /* GOPHER server due to Shawn Hart at the University of Delaware. */
- /* GOPHER client due to Steve Bacher at Draper Laboratory. */
- /* SAS modifications due to Dale Ingold at SAS Institute, Inc. */
- /* */
- /* This software is provided on an "AS IS" basis. All warranties, */
- /* including the implied warranties of merchantability and fitness, */
- /* are expressly denied. */
- /* */
- /* Provided this copyright notice is included, this software may */
- /* be freely distributed and not offered for sale. */
- /* */
- /* Changes or modifications may be made and used only by the maker */
- /* of same, and not further distributed. Such modifications should */
- /* be mailed to the author for consideration for addition to the */
- /* software and incorporation in subsequent releases. */
- /* */
- /********************************************************************/
-
- #pragma csect(code, "GG@TEMP")
- #pragma csect(static,"GG$TEMP")
-
- #include "gg.h"
-
- /*===================================================================*/
-
- FILE *
- GGtemp(RECV *R,
- TEMPFILE *tp,
- TMPFUN tempfunction
- )
- {
- FILE *rfp = NULL;
-
- switch (tempfunction) {
- case TEMP_CREATE:
- strcpy(tp->ddname,"dd:");
- if (!tmpnam(tp->dsname)) {
- fprintf(stderr, "GGtemp: Can't create temporary file\n");
- }
- if (GGalloc(tp->dsname,tp->ddname+3,SEQ,500) != SEQ) {
- fprintf(stderr, "GGtemp: Can't allocate temporary file\n");
- }
- if (tp->crmode == RBIN) rfp = OPEN_FTP_BINARY_FILE(tp->ddname);
- else rfp = OPEN_FTP_TEMP_FILE(tp->ddname);
- if (!rfp) {
- perror(tp->dsname);
- fprintf(stderr, "GOPHER: Can't open temporary file\n");
- }
- tp->fp = rfp;
- break;
- case TEMP_CLOSE:
- if (fclose(tp->fp) < 0) {
- fprintf(stderr, "GGtemp: Can't close temporary file\n");
- }
- else rfp = tp->fp;
- break;
- case TEMP_REMOVE:
- GGunalc(tp->ddname+3);
- if (remove(tp->dsname) < 0) {
- fprintf(stderr, "GGtemp: Can't remove temporary file\n");
- }
- else rfp = tp->fp;
- break;
-
- }
- if (!rfp) {
- GGbarf(R, "Sorry, the GOPHER server couldn't service the request");
- }
- return rfp;
-
- }
-
- ./ ADD NAME=GGTNET
-
- /********************************************************************/
- /* */
- /* Copyright (c) The Charles Stark Draper Laboratory, 1992, 1993 */
- /* GOPHER server due to Shawn Hart at the University of Delaware. */
- /* GOPHER client due to Steve Bacher at Draper Laboratory. */
- /* SAS modifications due to Dale Ingold at SAS Institute, Inc. */
- /* */
- /* This software is provided on an "AS IS" basis. All warranties, */
- /* including the implied warranties of merchantability and fitness, */
- /* are expressly denied. */
- /* */
- /* Provided this copyright notice is included, this software may */
- /* be freely distributed and not offered for sale. */
- /* */
- /* Changes or modifications may be made and used only by the maker */
- /* of same, and not further distributed. Such modifications should */
- /* be mailed to the author for consideration for addition to the */
- /* software and incorporation in subsequent releases. */
- /* */
- /********************************************************************/
-
- #pragma csect(code, "GG@TNET ")
- #pragma csect(static,"GG$TNET ")
- #include "gg.h"
-
- /* Additional code by Denis De La Roca <denis@mvs.oac.ucla.edu> */
-
- /****** Gopher TELNET interface. *************************************/
-
- Bool
- GGtnet(gp,ip,how)
- RGGCB *gp;
- RINFO *ip;
- GOHOW how;
- {
- int tsorc;
- int cnt = 0;
- char *userid = NULL;
- char *password = NULL;
- char tpath [128];
- char tsocmd [256];
- char tstuff [256];
-
- switch (how) {
- case AS_NORMAL: break;
- default:
- ERR1("TELNET interface cannot be viewed as a file.");
- return FALSE;
- }
-
- ISPF("CONTROL DISPLAY LINE");
-
- /* Parse userid/password for Xtelnet's autologin */
-
- #ifdef XTELNET_AUTOLOGIN
-
- if (EQUAL(gp->mytelnet, "XTELNET") && *ip->path) {
-
- strcpy(tpath, ip->path);
- userid = tpath;
- password = strchr(tpath, ',');
- if (password) {
- *password = '\0';
- password = strchr(password + 1, ':');
- if (password) {
- if (!memcmp(password - 7, "assword", 7)) password += 2;
- else password = NULL;
- }
- }
- cnt += sprintf(tsocmd+cnt, "%s -l %s", gp->mytelnet, userid);
- if (password)
- cnt += sprintf(tsocmd+cnt, "/%s", password);
- cnt += sprintf(tsocmd+cnt, " %s", ip->host);
- if (ip->port > 0)
- cnt += sprintf(tsocmd+cnt, " %d", ip->port);
- }
-
- else { /* IBM's Telnet does not support autologin */
-
- #endif
-
- /* Print note only if we have non-null path */
-
- if (*ip->path) {
- fprintf(stderr,"Note: Login as user: %s\n\n", ip->path);
- }
-
- if (ip->port==0) sprintf(tsocmd,"%s %s",gp->mytelnet,ip->host);
- else sprintf(tsocmd,"%s %s %d",gp->mytelnet,ip->host,ip->port);
-
- #ifdef XTELNET_AUTOLOGIN
-
- }
-
- #endif
-
- if ((tsorc = GGtso(tsocmd)) != 0) {
- ERR3("Command \"%s\" returned code %d", tsocmd, tsorc);
- }
-
- ISPF("CONTROL DISPLAY REFRESH");
-
- return TRUE;
- }
-
- ./ ADD NAME=GGTSO
-
- /********************************************************************/
- /* */
- /* Copyright (c) The Charles Stark Draper Laboratory, 1992, 1993 */
- /* GOPHER server due to Shawn Hart at the University of Delaware. */
- /* GOPHER client due to Steve Bacher at Draper Laboratory. */
- /* SAS modifications due to Dale Ingold at SAS Institute, Inc. */
- /* */
- /* This software is provided on an "AS IS" basis. All warranties, */
- /* including the implied warranties of merchantability and fitness, */
- /* are expressly denied. */
- /* */
- /* Provided this copyright notice is included, this software may */
- /* be freely distributed and not offered for sale. */
- /* */
- /* Changes or modifications may be made and used only by the maker */
- /* of same, and not further distributed. Such modifications should */
- /* be mailed to the author for consideration for addition to the */
- /* software and incorporation in subsequent releases. */
- /* */
- /********************************************************************/
-
- /********************************************************************/
- /* */
- /* Thanks to Michael Van Norman for this code. */
- /* */
- /********************************************************************/
-
- #pragma csect(code, "GG@TSO ")
- #pragma csect(static,"GG$TSO ")
- #include "gg.h"
-
- #pragma linkage(ikjeftsr,OS)
-
- #define _IKJEFTSR_FLAGS_AUTH 0x00000000
- #define _IKJEFTSR_FLAGS_COMMAND 0x00000001
- #define _IKJEFTSR_FLAGS_DUMP 0x00000100
- #define _IKJEFTSR_FLAGS_NODUMP 0x00000000
- #define _IKJEFTSR_FLAGS_PROGRAM 0x00000002
- #define _IKJEFTSR_FLAGS_UNAUTH 0x00010000
-
- /****** Issue TSO command. *******************************************/
-
- int
- GGtso(command)
- char *command;
- {
- int flags = _IKJEFTSR_FLAGS_COMMAND +
- _IKJEFTSR_FLAGS_UNAUTH;
- int commandLength = strlen(command);
- int rc = 0;
- int returnCode = 0;
- int reasonCode = 0;
- int abendCode = 0;
-
- static int (*ikjeftsr)() = NULL;
-
- if (!ikjeftsr) {
- int tsoEntryAddress;
-
- tsoEntryAddress = 0x00000010; /* Address of CVT */
- tsoEntryAddress = *(int *)(tsoEntryAddress);
- tsoEntryAddress += 0x9C;/* /* Offset of TVT in CVT */
- tsoEntryAddress = *(int *)(tsoEntryAddress);
- tsoEntryAddress += 0x10;/* /* TSVTASF-TSVT (from IKJTSVT) */
- tsoEntryAddress = *(int *)(tsoEntryAddress);
- #ifndef SASC
- ikjeftsr = (int (*)())(tsoEntryAddress);
- #else
- ikjeftsr = (__ibmos int (*)())(tsoEntryAddress);
- #endif
- }
-
- if (!ikjeftsr) {
- fprintf(stderr,
- "Cannot execute TSO commands, can't fetch IKJEFTSR.\n");
- return -2;
- }
-
- rc = (*ikjeftsr)(&flags, command, &commandLength,
- &returnCode, &reasonCode,
- (int *)((int)(&abendCode) | 0x80000000));
-
- if (rc != 0) {
- if (rc > 4) {
- fprintf(stderr,"Command failed:%s\n",command);
- if (rc == 20 && reasonCode == 40)
- fprintf(stderr,"Command was not found.\n");
- else fprintf(stderr,
- "rc=%d,returncode=%d,reasoncode=%d,abendcode=%8.8x\n",
- rc, returnCode, reasonCode, abendCode);
- }
- if (abendCode != 0) rc = -1;
- else rc = returnCode;
- }
-
- return rc;
- }
-
- ./ ADD NAME=GGTYPE
-
- /********************************************************************/
- /* */
- /* Copyright (c) The Charles Stark Draper Laboratory, 1992, 1993 */
- /* GOPHER server due to Shawn Hart at the University of Delaware. */
- /* GOPHER client due to Steve Bacher at Draper Laboratory. */
- /* SAS modifications due to Dale Ingold at SAS Institute, Inc. */
- /* */
- /* This software is provided on an "AS IS" basis. All warranties, */
- /* including the implied warranties of merchantability and fitness, */
- /* are expressly denied. */
- /* */
- /* Provided this copyright notice is included, this software may */
- /* be freely distributed and not offered for sale. */
- /* */
- /* Changes or modifications may be made and used only by the maker */
- /* of same, and not further distributed. Such modifications should */
- /* be mailed to the author for consideration for addition to the */
- /* software and incorporation in subsequent releases. */
- /* */
- /********************************************************************/
-
- #pragma csect(code, "GG@TYPE ")
- #pragma csect(static,"GG$TYPE ")
- #include "gg.h"
-
- /*********************************************************************/
-
- char *
- GGtype(GOPHERTYPE t)
- {
-
- switch (t) {
- case GOPHER_FILE: return "File ";
- case GOPHER_DIRECTORY: return "Directory";
- case GOPHER_CSO: return "Cso ";
- case GOPHER_ERROR: return "Error ";
- case GOPHER_MAC_BINHEX: return "Binhex ";
- case GOPHER_DOS_BINARCH: return "Binarch ";
- case GOPHER_UUENCODE: return "Uuencode ";
- case GOPHER_WAIS: return "Index ";
- case GOPHER_TELNET: return "Telnet ";
- case GOPHER_TN3270: return "TN3270 ";
- case GOPHER_BINARY: return "Binary ";
- case GOPHER_IMAGE: return "Image ";
- case GOPHER_BOOKMANAGER: return "BookMgr ";
- case GOPHER_COMMENT: return " ";
- case GOPHER_REDUNDANT: return "Redundant";
- case GOPHER_WHOIS: return "Whois ";
- default: return "Unknown ";
- }
- }
-
- ./ ADD NAME=GGUNALC
-
- /********************************************************************/
- /* */
- /* Copyright (c) The Charles Stark Draper Laboratory, 1992, 1993 */
- /* GOPHER server due to Shawn Hart at the University of Delaware. */
- /* GOPHER client due to Steve Bacher at Draper Laboratory. */
- /* SAS modifications due to Dale Ingold at SAS Institute, Inc. */
- /* */
- /* This software is provided on an "AS IS" basis. All warranties, */
- /* including the implied warranties of merchantability and fitness, */
- /* are expressly denied. */
- /* */
- /* Provided this copyright notice is included, this software may */
- /* be freely distributed and not offered for sale. */
- /* */
- /* Changes or modifications may be made and used only by the maker */
- /* of same, and not further distributed. Such modifications should */
- /* be mailed to the author for consideration for addition to the */
- /* software and incorporation in subsequent releases. */
- /* */
- /********************************************************************/
-
- #pragma csect(code, "GG@UNALC")
- #pragma csect(static,"GG$UNALC")
- #include "gg.h"
- #include "ggsvc99.h"
-
- /****** Unallocate a data set. ***************************************/
-
- Bool
- GGunalc(ddname)
- char *ddname;
- {
- __S99parms stuff99; /* The manual has it wrong. No "struct". */
- int rc;
- TEXTUNIT *tu [2];
- TEXTUNIT tu_ddn;
- TEXTUNIT tu_una;
-
- if (!ddname || !*ddname) return TRUE; /* if no ddname to free */
-
- CLEAR(&stuff99);
-
- stuff99.__S99RBLN = 20;
- stuff99.__S99VERB = S99VRBUN;
- stuff99.__S99FLAG1 = 0;
- stuff99.__S99ERROR = 0;
- stuff99.__S99INFO = 0;
- stuff99.__S99TXTPP = tu;
- stuff99.__S99FLAG2 = 0;
-
- tu[0] = &tu_ddn;
- tu[1] = &tu_una;
- *(int *)&tu[1] |= 0x80000000;
-
- tu_ddn.key = DUNDDNAM;
- tu_ddn.num = 1;
- tu_ddn.ent.len = strlen(ddname);
- copy_uppercase(tu_ddn.ent.prm,ddname);
-
- tu_una.key = DUNUNALC;
- tu_una.num = 0;
-
- rc = svc99(&stuff99);
-
- if (rc == 0) return TRUE;
- else if (stuff99.__S99ERROR == 0x0438) /* not freed, is not allocated*/
- return TRUE;
- else {
- GGdfail(rc,&stuff99);
- return FALSE;
- }
- }
-
- ./ ADD NAME=GGVIEW
-
- /********************************************************************/
- /* */
- /* Copyright (c) The Charles Stark Draper Laboratory, 1992, 1993 */
- /* GOPHER server due to Shawn Hart at the University of Delaware. */
- /* GOPHER client due to Steve Bacher at Draper Laboratory. */
- /* SAS modifications due to Dale Ingold at SAS Institute, Inc. */
- /* */
- /* This software is provided on an "AS IS" basis. All warranties, */
- /* including the implied warranties of merchantability and fitness, */
- /* are expressly denied. */
- /* */
- /* Provided this copyright notice is included, this software may */
- /* be freely distributed and not offered for sale. */
- /* */
- /* Changes or modifications may be made and used only by the maker */
- /* of same, and not further distributed. Such modifications should */
- /* be mailed to the author for consideration for addition to the */
- /* software and incorporation in subsequent releases. */
- /* */
- /********************************************************************/
-
- #pragma csect(code, "GG@VIEW ")
- #pragma csect(static,"GG$VIEW ")
- #include "gg.h"
-
- struct cmddesc {
- char command_name[COMMANDSIZE];
- Bool (*command_processor)();
- };
-
- struct browser {
- GOPHERINFO *ip;
- TEXTHDR *thp; /* text header pointer */
- TEXTLINE **tv; /* text vector */
- char *bda; /* dynamic area address */
- char *work; /* find work area address */
- char *firstpos; /* beginning of actual data */
- char *lastpos; /* end of actual data */
- int depth; /* dynamic area depth */
- int lvl; /* last visible line */
- int size; /* dynamic area size */
- int more_rows; /* Scroll request row count */
- int rowfactor; /* # physical rows per line */
- int screenbump; /* # physical rows * width */
- int top; /* top row number */
- int total; /* total number of rows */
- int coloff; /* offset from LEFT/RIGHT */
- int cols; /* 1 if COLS done, else 0 */
- int maxlen; /* maximum text length */
- int maxcoloff; /* maximum right scroll */
- int find_count; /* used by FIND ALL */
- int find_row; /* row where last found */
- int find_col; /* col where last found */
- int found_row; /* row where last found */
- int found_col; /* col where last found */
- int csrpos; /* cursor position */
- int find_csrpos; /* col where last found */
- int found_left; /* pos left of found string */
- int found_right; /* pos right of found string*/
- Bool override_scroll;/* set by some commands */
- Bool highlighted; /* set if FIND highlights */
- Bool reinit_browse; /* set if text changed */
- Bool exit_browse; /* set if browse must exit */
- Bool find_hit_end; /* top/bottom of data reach */
- char cursor [9]; /* cursor field name */
- char find_cursor[9]; /* row where last found */
- char title [81]; /* title */
- char cols_line [81]; /* cols line */
- char zcmd [81]; /* command input */
- };
-
- /******* EXTRACT command **********************************************/
-
- static Bool
- process_extract_command(gp,bp,operands)
- RGGCB *gp;
- struct browser *bp;
- char *operands;
- {
- RINFO *ip = bp->ip;
-
- gp->extract_file = NULL;
-
- ISPF("CONTROL DISPLAY SAVE");
- (void)GGxtx(gp,ip,EXTRACT_IT); /* Extract text */
- ISPF("CONTROL DISPLAY RESTORE");
-
- return TRUE;
- }
-
- /******* PRINT command ************************************************/
-
- static Bool
- process_print_command(gp,bp,operands)
- RGGCB *gp;
- struct browser *bp;
- char *operands;
- {
- RINFO *ip = bp->ip;
-
- gp->extract_file = NULL;
-
- ISPF("CONTROL DISPLAY SAVE");
- (void)GGxtx(gp,ip,PRINT_IT); /* Print text */
- ISPF("CONTROL DISPLAY RESTORE");
-
- return TRUE;
- }
-
- /******* INFO command. ************************************************/
-
- static Bool
- process_info_command(gp,bp,operands)
- RGGCB *gp;
- struct browser *bp;
- char *operands;
- {
- RINFO *ip = bp->ip;
-
- if (!GGinfo(gp,ip)) return FALSE;
-
- ISPF("CONTROL DISPLAY SAVE");
- (void)GGvtx(gp,NULL,TRUE); /* View text */
- ISPF("CONTROL DISPLAY RESTORE");
-
- return TRUE;
- }
-
- /******* BOOKMARK command. ********************************************/
-
- static Bool
- process_bookmark_command(gp,bp,operands)
- RGGCB *gp;
- struct browser *bp;
- char *operands;
- {
- RINFO *ip = bp->ip;
-
- if (!GGinfo(gp,ip)) return FALSE;
-
- gp->extract_file = NULL;
-
- ISPF("CONTROL DISPLAY SAVE");
- (void)GGxtx(gp,ip,BOOKMARK_IT); /* save as bookmark */
- ISPF("CONTROL DISPLAY RESTORE");
-
- return TRUE;
- }
-
- /******* OPTIONS command **********************************************/
-
- static Bool
- process_options_command(gp,bp,operands)
- RGGCB *gp;
- struct browser *bp;
- char *operands;
- {
-
- GGdsopt(gp,operands);
-
- return TRUE;
- }
-
- /******* QUIT command *************************************************/
-
- static Bool
- process_quit_command(gp,bp,operands)
- RGGCB *gp;
- struct browser *bp;
- char *operands;
- {
-
- gp->quit = TRUE;
-
- return TRUE;
- }
-
- /******* COLS command *************************************************/
-
- static Bool
- process_cols_command(gp,bp,operands)
- RGGCB *gp;
- Rstruc browser *bp;
- char *operands;
- {
-
- bp->cols = 1;
- *bp->cols_line = '\0';
- bp->reinit_browse = TRUE;
- return TRUE;
- }
-
- /******* RESET command ************************************************/
-
- static Bool
- process_reset_command(gp,bp,operands)
- RGGCB *gp;
- Rstruc browser *bp;
- char *operands;
- {
-
- bp->cols = 0;
- *bp->cols_line = '\0';
- bp->reinit_browse = TRUE;
- return TRUE;
- }
-
- /******* DISPLAY command **********************************************/
-
- static Bool
- process_display_command(gp,bp,operands)
- RGGCB *gp;
- Rstruc browser *bp;
- char *operands;
- {
- unsigned int u;
-
- switch (strlen(operands)) {
- case 1: gp->text_dispchar = operands[0];
- break;
- case 2: if (1 != sscanf(operands,"%x",&u)) {
- ERR1("Invalid hex character representation.");
- return FALSE;
- }
- gp->text_dispchar = u;
- break;
- default:
- ERR1("A single character must be specified.");
- return FALSE;
- }
- bp->reinit_browse = TRUE;
- return TRUE;
- }
-
- /******* LOCATE command ***********************************************/
-
- static Bool
- process_locate_command(gp,bp,operands)
- RGGCB *gp;
- Rstruc browser *bp;
- char *operands;
- {
- int locnum;
- char junk[72];
-
- if (1 != sscanf(operands, "%d %s", &locnum, junk)) {
- ERR1("The LOCATE command requires a line number.");
- return FALSE;
- }
-
- bp->top = locnum;
- bp->more_rows = 0;
- bp->override_scroll = TRUE;
- bp->reinit_browse = TRUE;
- return TRUE;
- }
-
- /***** Helper functions for FIND **************************************/
-
- /*--------------------------------------------------------------------*
- * Get quoted FIND string. *
- *--------------------------------------------------------------------*/
-
- static char *
- get_quoted_find_string(gp,cp,qform)
- RGGCB *gp;
- register char *cp;
- char *qform;
- {
- char quote = *cp;
- char termchar = '\0';
-
- for (cp++;;cp++) {
- if (*cp == quote) {
- switch (*(cp+1)) {
- case '\0':
- case ' ': termchar = '\0'; break;
- case 'c':
- case 'C': termchar = 'C' ; break;
- case 't':
- case 'T': termchar = 'T' ; break;
- case 'x':
- case 'X': termchar = 'X' ; break;
- case 'p':
- case 'P': termchar = 'P' ; break;
- default: continue;
- }
- if (termchar) {
- switch (*(cp+2)) {
- case '\0':
- case ' ': break;
- default: continue;
- }
- if (*qform != FIND_QUOTED) {
- ERR1(
- "Invalid string; Do not surround a quoted string with letters.");
- *qform = FIND_BADFORM;
- return NULL;
- }
- else {
- switch (termchar) {
- case 'C': *qform = FIND_C; break;
- case 'T': *qform = FIND_T; break;
- case 'X': *qform = FIND_X; break;
- case 'P': *qform = FIND_P; break;
- }
- *cp = '\0'; /* kill the quote because it's the character */
- cp++; /* that the caller will kill, not the quote */
- }
- }
- break;
- }
- else if (!*cp) {
- ERR1(
- "Missing quote; The FIND command requires balanced quote marks.");
- *qform = FIND_BADFORM;
- return NULL;
- }
- }
- return cp;
- }
-
- /*--------------------------------------------------------------------*
- * Get FIND operand. *
- *--------------------------------------------------------------------*/
-
- static char *
- get_find_operand(gp,opp,qform)
- RGGCB *gp;
- char **opp;
- char *qform;
- {
- register char *cp = skip_ISPF_whitespace(*opp);
- char *start = NULL;
-
- if (!*cp) return NULL;
- if (*cp == '\'' || *cp == '"') {
- start = cp+1;
- *qform = FIND_QUOTED;
- if (!(cp = get_quoted_find_string(gp,cp,qform))) return NULL;
- }
- else if ((*(cp+1) == '\'' || *(cp+1) == '"')) {
- switch (*cp) {
- case 'c':
- case 'C': *qform = FIND_C; break;
- case 't':
- case 'T': *qform = FIND_T; break;
- case 'x':
- case 'X': *qform = FIND_X; break;
- case 'p':
- case 'P': *qform = FIND_P; break;
- default: *qform = FIND_UNQUOTED; break;
- }
- if (*qform != FIND_UNQUOTED) {
- cp++;
- start = cp+1;
- if (!(cp = get_quoted_find_string(gp,cp,qform))) return NULL;
- }
- else {
- start = cp;
- find_ISPF_whitespace(cp,start);
- }
- }
- else {
- start = cp;
- *qform = FIND_UNQUOTED;
- find_ISPF_whitespace(cp,start);
- }
- if (*cp) {
- *cp = '\0';
- *opp = cp+1;
- }
- else *opp = cp;
- return start;
- }
-
- /*--------------------------------------------------------------------*
- * Find it. *
- *--------------------------------------------------------------------*/
-
- #define REND (r+(*tpp)->tab_expanded_text_length)
- #define PRECEDED_BY_VERBIAGE (q>r && isalnum(*(q-1)))
- #define FOLLOWED_BY_VERBIAGE (q+findlen<REND && isalnum(*(q+findlen)))
-
- static Bool
- find_it(gp,bp,find_string,findlen,
- find_type,find_what,find_trans,
- find_left_bound,find_right_bound)
- RGGCB *gp;
- Rstruc browser *bp;
- char *find_string;
- int findlen;
- char find_type; /* chars word prefix suffix */
- char find_what; /* next prev first last all */
- char find_trans; /* caps asis generic */
- int find_left_bound;
- int find_right_bound;
- {
- TEXTLINE **tpp;
- char *p;
- char *q;
- char *r;
- int row = bp->find_row;
- int col = bp->find_col;
- int lcol = find_left_bound - 1;
- int rcol = find_right_bound - 1;
- int ecol;
- int complen;
- Bool backward_find;
-
- switch (find_what) {
- case FIND_NEXT:
- if (bp->find_hit_end) {
- bp->find_hit_end = FALSE;
- row = 0;
- col = lcol;
- }
- else if (EQUAL(bp->find_cursor,"GGBDYNA")) {
- row = bp->top+((bp->find_csrpos-1)/80)-bp->cols-1;
- col = (bp->find_csrpos-1) % 80 + bp->coloff;
- if (++col >= bp->maxlen) {
- row++;
- col = lcol;
- }
- }
- else {
- row = bp->top - 1;
- if (row < 0) row = 0;
- col = lcol;
- }
- backward_find = FALSE;
- break;
- case FIND_PREV:
- if (bp->find_hit_end) {
- bp->find_hit_end = FALSE;
- row = bp->total - 1;
- col = rcol;
- }
- else if (EQUAL(bp->find_cursor,"GGBDYNA")) {
- row = bp->top+((bp->find_csrpos-1)/80)-bp->cols-1;
- col = (bp->find_csrpos-1) % 80 + bp->coloff;
- if (--col < 0) {
- row--;
- col = rcol;
- }
- }
- else {
- row = bp->total - 1;
- col = rcol;
- }
- backward_find = TRUE;
- break;
- case FIND_FIRST:
- bp->find_hit_end = FALSE;
- row = 0;
- col = lcol;
- backward_find = FALSE;
- break;
- case FIND_LAST:
- bp->find_hit_end = FALSE;
- row = bp->total - 1;
- col = rcol;
- backward_find = TRUE;
- break;
- case FIND_ALL:
- col++;
- backward_find = FALSE;
- break;
- }
-
- if (!backward_find) { /* forward find */
- if (col < lcol) col = lcol;
- else if (col > rcol) {
- col = lcol;
- row++;
- }
- for (tpp = &bp->tv[row]; row < bp->total; tpp++, col=lcol, row++) {
- ecol = (*tpp)->tab_expanded_text_length - 1;
- if (ecol > rcol) ecol = rcol;
- if (col > ecol) continue;
- p = (*tpp)->tab_expanded_text;
- if (find_trans == FIND_CAPS) {
- copy_uppercase(bp->work,p);
- r = bp->work;
- }
- else r = p;
- complen = ecol-col+1;
- for (q = r + col;;q++) {
- q = memchr(q,find_string[0],complen);
- if (!q) break;
- col = q - r;
- complen = ecol-col+1;
- if (complen < findlen) break;
- if (!memcmp(q,find_string,findlen)) {
- switch (find_type) {
- case FIND_CHARS: break;
- case FIND_WORD:
- if (PRECEDED_BY_VERBIAGE || FOLLOWED_BY_VERBIAGE)
- continue;
- break;
- case FIND_PREFIX:
- if (PRECEDED_BY_VERBIAGE || !FOLLOWED_BY_VERBIAGE)
- continue;
- break;
- case FIND_SUFFIX:
- if (!PRECEDED_BY_VERBIAGE || FOLLOWED_BY_VERBIAGE)
- continue;
- break;
- }
- bp->find_row = row;
- bp->find_col = col;
- return TRUE;
- }
- }
- }
- bp->find_row = 0;
- bp->find_col = 0;
- bp->find_hit_end = TRUE;
- return FALSE;
- }
- else { /* backward find */
- if (row >= bp->total) row = bp->total - 1;
- if (col > rcol-findlen+1) col = rcol-findlen+1;
- else if (col < lcol) {
- col = rcol-findlen+1;
- row--;
- }
- for (tpp=&bp->tv[row]; row >= 0; tpp--, col=rcol-findlen+1, row--) {
- ecol = (*tpp)->tab_expanded_text_length - 1;
- if (ecol > rcol) ecol = rcol;
- if (col > ecol) col = ecol;
- p = (*tpp)->tab_expanded_text;
- if (find_trans == FIND_CAPS) {
- copy_uppercase(bp->work,p);
- r = bp->work;
- }
- else r = p;
- for (q = r + col; q >= r; q--) {
- if (!memcmp(q,find_string,findlen)) {
- switch (find_type) {
- case FIND_CHARS: break;
- case FIND_WORD:
- if (PRECEDED_BY_VERBIAGE || FOLLOWED_BY_VERBIAGE)
- continue;
- break;
- case FIND_PREFIX:
- if (PRECEDED_BY_VERBIAGE || !FOLLOWED_BY_VERBIAGE)
- continue;
- break;
- case FIND_SUFFIX:
- if (!PRECEDED_BY_VERBIAGE || FOLLOWED_BY_VERBIAGE)
- continue;
- break;
- }
- col = q - r;
- bp->find_row = row;
- bp->find_col = col;
- return TRUE;
- }
- }
- }
- bp->find_row = bp->total - 1;
- bp->find_col = bp->maxlen;
- bp->find_hit_end = TRUE;
- return FALSE;
- }
- }
-
- /********* FIND command ***********************************************/
-
- static Bool
- process_find_command(gp,bp,operands)
- RGGCB *gp;
- Rstruc browser *bp;
- char *operands;
- {
- char *find_operand [64];
- char *show_type;
- char *cp;
- char *opcopy;
- char *op;
- char *p;
- char *q;
- int find_operand_count = 0;
- int ox;
- int find_left_bound;
- int find_right_bound;
- int n;
- int len;
- int findlen;
- Bool finderror = FALSE;
- Bool out_of_bounds = FALSE;
- Bool hit_end = FALSE;
- Bool find_string_given = FALSE;
- Bool find_what_given = FALSE;
- Bool find_type_given = FALSE;
- Bool find_left_bound_given = FALSE;
- Bool find_right_bound_given = FALSE;
- char find_what; /* next prev first last all */
- char find_type; /* chars word prefix suffix */
- char find_trans; /* caps asis generic */
- char find_form; /* unquoted quoted c x t p */
- char ff; /* unquoted quoted c x t p */
- char find_qform [64];
- char operand_copy [81];
- char find_string [81];
- char temp [81];
- char show_string [129];
- char shortmsg [129];
- char longmsg [129];
-
- strcpy(operand_copy,operands);
-
- for (ox = 0, opcopy = operand_copy; ox < 64; ox++) {
- ff = FIND_UNQUOTED;
- op = get_find_operand(gp,&opcopy,&ff);
- if (ff == FIND_BADFORM) return FALSE;
- if (!op) break;
- find_operand[ox] = op;
- find_qform[ox] = ff;
- find_operand_count++;
- }
-
- if (find_operand_count == 0) {
- if (!*gp->text_find_string) {
- ERR1("The first FIND command requires an operand.");
- return FALSE;
- }
- strcpy(find_string,gp->text_find_string);
- find_what = gp->text_find_what;
- find_type = gp->text_find_type;
- find_trans = gp->text_find_trans;
- find_left_bound = gp->text_find_left_bound;
- find_right_bound = gp->text_find_right_bound;
- }
- else {
- find_what = FIND_NEXT;
- find_type = FIND_CHARS;
- find_trans = FIND_CAPS;
- find_left_bound = 1;
- find_right_bound = bp->maxlen;
- for (ox = 0; ox < find_operand_count; ox++) {
- op = find_operand[ox];
- ff = find_qform[ox];
- if (ff != FIND_UNQUOTED) {
- if (find_string_given) finderror = TRUE;
- else {
- strcpy(find_string,op);
- find_form = ff;
- find_string_given = TRUE;
- }
- }
- else {
- copy_uppercase(temp,op);
- if (EQUAL(temp,"*")) {
- if (find_string_given) finderror = TRUE;
- else {
- strcpy(find_string,gp->text_find_string);
- find_form = ff;
- find_string_given = TRUE;
- }
- }
- else if (find_operand_count == 1) {
- strcpy(find_string,op);
- find_form = ff;
- find_string_given = TRUE;
- }
- else if (EQUAL(temp,"NEXT")) {
- if (find_what_given) finderror = TRUE;
- else {
- find_what = FIND_NEXT;
- find_what_given = TRUE;
- }
- }
- else if (EQUAL(temp,"PREV")) {
- if (find_what_given) finderror = TRUE;
- else {
- find_what = FIND_PREV;
- find_what_given = TRUE;
- }
- }
- else if (EQUAL(temp,"FIRST")) {
- if (find_what_given) finderror = TRUE;
- else {
- find_what = FIND_FIRST;
- find_what_given = TRUE;
- }
- }
- else if (EQUAL(temp,"LAST")) {
- if (find_what_given) finderror = TRUE;
- else {
- find_what = FIND_LAST;
- find_what_given = TRUE;
- }
- }
- else if (EQUAL(temp,"ALL")) {
- if (find_what_given) finderror = TRUE;
- else {
- find_what = FIND_ALL;
- find_what_given = TRUE;
- }
- }
- else if (EQUAL(temp,"CHARS")) {
- if (find_type_given) finderror = TRUE;
- else {
- find_type = FIND_CHARS;
- find_type_given = TRUE;
- }
- }
- else if (EQUAL(temp,"WORD")) {
- if (find_type_given) finderror = TRUE;
- else {
- find_type = FIND_WORD;
- find_type_given = TRUE;
- }
- }
- else if (EQUAL(temp,"PREFIX") || EQUAL(temp,"PRE")) {
- if (find_type_given) finderror = TRUE;
- else {
- find_type = FIND_PREFIX;
- find_type_given = TRUE;
- }
- }
- else if (EQUAL(temp,"SUFFIX") || EQUAL(temp,"SUF")) {
- if (find_type_given) finderror = TRUE;
- else {
- find_type = FIND_SUFFIX;
- find_type_given = TRUE;
- }
- }
- else if (*(temp+strspn(temp,"0123456789")) == '\0') {
- if (find_left_bound_given) {
- if (find_right_bound_given) finderror = TRUE;
- else {
- find_right_bound = atoi(temp);
- if (find_right_bound > bp->maxlen) out_of_bounds = TRUE;
- find_right_bound_given = TRUE;
- }
- }
- else {
- find_left_bound = atoi(temp);
- if (find_right_bound < 1) out_of_bounds = TRUE;
- find_left_bound_given = TRUE;
- }
- }
- else {
- if (find_string_given) finderror = TRUE;
- else {
- strcpy(find_string,op);
- find_form = ff;
- find_string_given = TRUE;
- }
- }
- }
- }
- }
-
- if (out_of_bounds) {
- ERR2("Invalid bound; Bounds must lie between 1 and %d", bp->maxlen);
- return FALSE;
- }
- if (finderror) {
- ERR1("Put string in quotes; Conflicting or unknown parameter.");
- return FALSE;
- }
- len = strlen(find_string);
- if (find_string_given) bp->find_hit_end = FALSE;
- if (find_left_bound_given && find_right_bound_given
- && find_left_bound > find_right_bound) {
- n = find_left_bound;
- find_left_bound = find_right_bound;
- find_right_bound = n;
- }
- else if (find_left_bound_given && !find_right_bound_given) {
- find_right_bound = find_left_bound + len - 1;
- }
- if (find_string_given) {
- switch (find_form) {
- case FIND_UNQUOTED: find_trans = FIND_CAPS; break;
- case FIND_QUOTED: find_trans = FIND_CAPS; break;
- case FIND_C: find_trans = FIND_ASIS; break;
- case FIND_T: find_trans = FIND_CAPS; break;
- case FIND_P: find_trans = FIND_GENERIC; break;
- case FIND_X: find_trans = FIND_HEX;
- if (len % 2 != 0) {
- ERR1("Odd number of characters in hex string.");
- return FALSE;
- }
- if (len != strspn(find_string,"0123456789abcdefABCDEF")) {
- ERR1("Invalid (non-hex) characters in hex string.");
- return FALSE;
- }
- for (p = find_string, q = find_string; *p; p += 2, *q++) {
- sprintf(temp,"0x%2.2s",p);
- sscanf(temp,"%x",&n);
- *q = (char)n;
- }
- *q = '\0';
- len = strlen(find_string);
- break;
- }
- }
-
- /* Store parameters for next Repeat Find operation. */
-
- strcpy(gp->text_find_string,find_string);
- switch (find_what) {
- case FIND_PREV:
- case FIND_LAST: gp->text_find_what = FIND_PREV; break;
- default: gp->text_find_what = FIND_NEXT; break;
- }
- gp->text_find_type = find_type;
- gp->text_find_trans = find_trans;
- gp->text_find_left_bound = find_left_bound;
- gp->text_find_right_bound = find_right_bound;
-
- if (!*find_string) {
- ERR1("A null string is not allowed for the FIND command.");
- return FALSE;
- }
-
- if (bp->total == 0) {
- ERR1("There is no text to search.");
- return FALSE;
- }
-
- strcpy(bp->zcmd,"");
-
- switch (find_type) {
- case FIND_CHARS: show_type = "Chars"; break;
- case FIND_WORD: show_type = "Word"; break;
- case FIND_PREFIX: show_type = "Prefix"; break;
- case FIND_SUFFIX: show_type = "Suffix"; break;
- default: show_type = "Text"; break;
- }
-
- switch (find_trans) {
- case FIND_ASIS: strcpy(show_string+0,"C'");
- strcpy(show_string+2,find_string);
- strcat(show_string,"'");
- break;
- case FIND_GENERIC: strcpy(show_string+0,"P'");
- strcpy(show_string+2,find_string);
- strcat(show_string,"'");
- break;
- case FIND_HEX: strcpy(show_string+0,"X'");
- for (p=find_string,q=show_string+2;*p;p++,q+=2) {
- sprintf(q,"%2.2X",*p);
- }
- strcat(show_string,"'");
- break;
- case FIND_CAPS:
- default: strcpy(show_string+0,"'");
- strcpy(show_string+1,find_string);
- strcat(show_string,"'");
- break;
- }
-
- switch (find_trans) {
- case FIND_CAPS:
- uppercase_in_place(find_string);
- break;
- case FIND_GENERIC:
- ERR1("The P'string' generic format is not supported.");
- return FALSE;
- }
-
- hit_end = bp->find_hit_end;
- findlen = strlen(find_string);
-
- if (find_what == FIND_ALL) {
- bp->find_count = 0;
- if (!find_it(gp,bp,find_string,findlen,
- find_type,FIND_FIRST,find_trans,
- find_left_bound, find_right_bound)) {
- sprintf(shortmsg,"No %s %s found",show_type,show_string);
- sprintf(longmsg,
- "%s %s - not found within columns %d to %d",
- show_type,show_string,find_left_bound,find_right_bound);
- ERR3("%24s;%s",shortmsg,longmsg);
- return FALSE;
- }
- bp->found_row = bp->find_row;
- bp->found_col = bp->find_col;
- bp->find_count = 1;
- while (find_it(gp,bp,find_string,findlen,
- find_type,FIND_ALL,find_trans,
- find_left_bound, find_right_bound)) {
- bp->find_count++;
- }
- bp->find_hit_end = FALSE;
- }
- else {
- if (!find_it(gp,bp,find_string,findlen,
- find_type,find_what,find_trans,
- find_left_bound, find_right_bound)) {
- if (hit_end) {
- sprintf(shortmsg,"No %s %s found",show_type,show_string);
- sprintf(longmsg,
- "%s %s - not found within columns %d to %d",
- show_type,show_string,find_left_bound,find_right_bound);
- ERR3("%24s;%s",shortmsg,longmsg);
- return FALSE;
- }
- else if (gp->text_find_what == FIND_PREV) {
- sprintf(shortmsg,"Top of data reached");
- sprintf(longmsg,
- "%s %s not found. Use RFIND to continue from bottom.",
- show_type, show_string);
- ERR3("%24s;%s",shortmsg,longmsg);
- }
- else {
- sprintf(shortmsg,"Bottom of data reached");
- sprintf(longmsg,
- "%s %s not found. Use RFIND to continue from top.",
- show_type, show_string);
- ERR3("%24s;%s",shortmsg,longmsg);
- }
- return FALSE;
- }
- bp->found_row = bp->find_row;
- bp->found_col = bp->find_col;
- }
- if (bp->found_row + 1 < bp->top
- || bp->found_row + 1 >= bp->top + bp->lvl - bp->cols) {
- bp->top = bp->found_row + 1 - 1;
- if (bp->top < 0) bp->top = 0;
- }
- if (bp->found_col < bp->coloff) {
- bp->coloff = bp->found_col;
- *bp->cols_line = '\0';
- }
- else if (bp->found_col+len > bp->coloff+80) {
- bp->coloff = bp->found_col + len - 80;
- if (bp->coloff < 0) bp->coloff = 0;
- *bp->cols_line = '\0';
- }
- strcpy(bp->cursor, "GGBDYNA");
- bp->csrpos = 80 * (bp->found_row - bp->top+bp->cols + 1)
- + bp->found_col - bp->coloff + 1;
- bp->found_left = bp->csrpos;
- bp->found_right = bp->found_left + len;
- bp->reinit_browse = TRUE;
-
- if (find_what == FIND_ALL) {
- sprintf(shortmsg,"%d %s %s",bp->find_count,show_type,show_string);
- sprintf(longmsg,
- "%s %s found %d times within columns %d to %d",
- show_type,show_string,bp->find_count,
- find_left_bound,find_right_bound);
- WARN3("%24s;%s",shortmsg,longmsg);
- }
- else {
- sprintf(shortmsg,"%s %s found",show_type,show_string);
- sprintf(longmsg,
- "Search for %s %s within columns %d to %d was successful",
- show_type,show_string, find_left_bound,find_right_bound);
- WARN3("%24s;%s",shortmsg,longmsg);
- }
- bp->find_row = bp->found_row;
- bp->find_col = bp->found_col;
- return TRUE;
- }
-
- /************ Fill browse dynamic area. *******************************/
-
- static void
- fill_browse_dynamic_area(gp,bp)
- RGGCB *gp;
- Rstruc browser *bp;
- {
- struct textline **tpp = NULL;
- register char *cp = NULL;
- register char *p;
- char *q;
- char *r;
- int i;
- int j;
- char temp[12];
-
- static char top_of_data_line[81] = "\
- ********************************* Top of data \
- **********************************";
-
- static char bottom_of_data_line[81] = "\
- ******************************** Bottom of data \
- ********************************";
-
- bp->lastpos = bp->bda + bp->size;
- bp->total = bp->thp->text_line_count;
- memset(bp->bda,' ',bp->size);
-
- if (bp->more_rows == -MAX_INT)
- bp->top = 0;
- else if (bp->more_rows == MAX_INT)
- bp->top = bp->total + 2 - bp->lvl + bp->cols;
- else bp->top += bp->more_rows;
-
- if (bp->top < 0) bp->top = 0;
- if (bp->top > bp->total) bp->top = bp->total + 1;
- i = bp->top;
- p = bp->bda;
-
- if (bp->cols > 0) {
- if (!*bp->cols_line) {
- for (j=bp->coloff+1,r=bp->cols_line; j<=bp->coloff+80; j++,r++) {
- if (j%10 == 0) {
- sprintf(temp,"%d",j%100);
- *r = temp[0];
- }
- else if (j%5 == 0) *r = '+';
- else *r = '-';
- }
- }
- memcpy(p,bp->cols_line,80);
- p += 80;
- }
-
- if (i == 0) {
- memcpy(p,top_of_data_line,80);
- p += 80;
- i++;
- }
-
- bp->firstpos = p;
-
- for (tpp=&bp->tv[i-1];i<=bp->total && p<bp->lastpos;i++,tpp++,p+=80) {
- if ((*tpp)->tab_expanded_text_length > bp->coloff) {
- cp = (*tpp)->tab_expanded_text + bp->coloff;
- for (j = 0, q = p; *cp && j < 80; j++, q++, cp++) {
- if (*cp > 0xf9 || *cp < 0x40) *q = gp->text_dispchar;
- else *q = *cp;
- }
- }
- }
-
- if (p < bp->lastpos) memcpy(p,bottom_of_data_line,80);
-
- return;
- }
-
- /************ Highlight browse text. **********************************/
-
- static void
- highlight_browse_text(gp,bp)
- RGGCB *gp;
- Rstruc browser *bp;
- {
- char *p;
-
- bp->highlighted = FALSE;
-
- if (bp->found_left) {
- if (EQUAL(bp->cursor,"GGBDYNA")) {
- for (p = bp->bda + bp->found_left - 1; p >= bp->firstpos; p--) {
- if (*p == ' ') {
- *p = DATAOUT_HIGH;
- bp->highlighted = TRUE;
- break;
- }
- }
- for (p = bp->bda + bp->found_right - 1; p <= bp->lastpos; p++) {
- if (*p == ' ') {
- *p = DATAOUT_LOW;
- bp->highlighted = TRUE;
- break;
- }
- }
- }
- }
-
- bp->found_left = 0;
- bp->found_right = 0;
-
- return;
- }
-
- /************ Display browse data. ************************************/
-
- static void
- display_browse_data(gp,bp)
- RGGCB *gp;
- Rstruc browser *bp;
- {
- struct cmddesc *cdp;
- char *cp;
- char *operands;
- int displayrc;
- int zscrolln;
- int leftcol;
- int rightcol;
- int command_index;
- Bool command_processed_ok;
- Bool is_max;
- Bool is_scroll_word;
- Bool is_scroll_cursor;
- SCROLL scroll_amount;
- char command [COMMANDSIZE+1];
- char zverb [16];
- char zscrolla [16];
- char longmsg [73];
- char ggbtitle [129];
- char ggbmsg [81];
- char temp1 [81];
- char temp2 [81];
-
- static struct cmddesc browse_commands[] = {
- {"L ",process_locate_command },
- {"LOC ",process_locate_command },
- {"LOCATE ",process_locate_command },
- {"F ",process_find_command },
- {"FIND ",process_find_command },
- {"RFIND ",process_find_command },
- {"YRFIND ",process_find_command },
- {"COL ",process_cols_command },
- {"COLS ",process_cols_command },
- {"RES ",process_reset_command },
- {"RESET ",process_reset_command },
- {"NOCOL ",process_reset_command },
- {"NOCOLS ",process_reset_command },
- {"DISP ",process_display_command },
- {"DISPL ",process_display_command },
- {"DISPLAY ",process_display_command },
- {"EXT ",process_extract_command },
- {"EXTR ",process_extract_command },
- {"EXTRACT ",process_extract_command },
- {"PRT ",process_print_command },
- {"PRNT ",process_print_command },
- {"PRINT ",process_print_command },
- {"INFO ",process_info_command },
- {"BOOK ",process_bookmark_command },
- {"BOOKMARK ",process_bookmark_command },
- {"OPT ",process_options_command },
- {"OPTION ",process_options_command },
- {"OPTIONS ",process_options_command },
- {"QUIT ",process_quit_command },
- {" ",NULL}
- };
-
- bp->more_rows = 0;
- bp->override_scroll = FALSE;
- bp->exit_browse = FALSE;
- memset (ggbtitle, '-', 80);
- strcpy (ggbtitle, "Browse - ");
- memcpy (ggbtitle + 9, bp->title, strlen(bp->title));
- *(ggbtitle + 9 + strlen(bp->title)) = ' ';
-
- if (!gp->setmsg) {
- leftcol = bp->coloff + 1;
- rightcol = bp->coloff + 80;
- if (bp->top > bp->total) strcpy(temp1,"");
- else sprintf(temp1, " Line %d of %d,", bp->top, bp->total);
- if (bp->maxlen <= 80)
- sprintf(temp2," Cols %d-%d",leftcol,rightcol);
- else sprintf(temp2," Cols %d-%d of %d",leftcol,rightcol,bp->maxlen);
- strcpy(ggbmsg,temp1);
- strcat(ggbmsg,temp2);
- strcpy (ggbtitle + 79 - strlen(ggbmsg), ggbmsg);
- }
-
- VPUT ("GGBTITLE ",ggbtitle);
- VPUT ("ZCMD " ,bp->zcmd);
- VPUTS("GGBDYNA " ,bp->bda, bp->size);
- VPUT ("GGBCUR " ,bp->cursor);
- IPUT ("GGBPOS " ,bp->csrpos);
- VPUT ("YRFIND " ,"ALIAS FIND");
-
- displayrc = GGdispl(gp,"GGMVIEW ");
- if (displayrc > 0) bp->exit_browse = TRUE;
-
- VPUT ("YRFIND " ,"");
- VGET ("GGBCUR " ,bp->cursor);
- VGET ("ZCMD " ,bp->zcmd);
- bp->lvl = IGET("GGBLVL ");
- bp->csrpos = IGET("GGBPOS ");
- strip_trailing_in_place(bp->cursor);
- strcpy(bp->find_cursor, bp->cursor);
- bp->find_csrpos = bp->csrpos;
- strcpy(bp->cursor,"");
- bp->csrpos = 1;
- if (bp->highlighted) bp->reinit_browse = TRUE;
- else bp->reinit_browse = FALSE;
-
- if (*bp->zcmd) {
- memset(command,' ',COMMANDSIZE);
- command_index = 0;
- for (cp = bp->zcmd; *cp && !isspace(*cp); cp++) {
- if (cp >= bp->zcmd+COMMANDSIZE) {
- ERR1(
- "Enter EXTract, PRT, BOOKmark, INFO, OPTions, or a browse command.");
- command_processed_ok = FALSE;
- }
- command[command_index++] = toupper(*cp);
- }
- while (*cp && isspace(*cp)) cp++;
- for (cdp=browse_commands; *cdp->command_name != ' '; cdp++) {
- if (!memcmp(command,cdp->command_name,COMMANDSIZE-1)) {
- command_processed_ok = (cdp->command_processor)(gp,bp,cp);
- cdp = NULL;
- break;
- }
- }
- if (cdp) {
- ERR1(
- "Enter EXTract, PRT, BOOKmark, INFO, OPTions, or a browse command.");
- command_processed_ok = FALSE;
- }
- if (command_processed_ok) strcpy(bp->zcmd,"");
- }
-
- if (gp->quit || bp->exit_browse) return;
-
- /* Check scroll request (ZSCROLLA direction, ZSCROLLN number).
- * Skip this if something was done by a command which causes
- * its own pseudo-scrolling to happen (like LOCATE).
- */
-
- if (!bp->override_scroll) {
-
- VGET("ZVERB " , zverb);
- VGET("ZSCROLLA ", zscrolla);
- zscrolln = IGET("ZSCROLLN ");
- is_max = FALSE;
- is_scroll_word = FALSE;
- is_scroll_cursor = FALSE;
-
- switch (zscrolla[0]) {
- case 'P':
- case 'H':
- case 'D': is_scroll_word = TRUE;
- break;
- case 'C': is_scroll_word = TRUE;
- is_scroll_cursor = TRUE;
- break;
- case 'M': is_max = TRUE;
- break;
- }
-
- if (EQUAL(zverb,"DOWN")) scroll_amount = DOWN;
- else if (EQUAL(zverb,"UP")) scroll_amount = UP;
- else if (EQUAL(zverb,"LEFT")) scroll_amount = LEFT;
- else if (EQUAL(zverb,"RIGHT")) scroll_amount = RIGHT;
- else scroll_amount = NO_SCROLL;
-
- switch (scroll_amount) {
- case NO_SCROLL:
- bp->more_rows = 0;
- break;
- case DOWN:
- if (is_max) bp->more_rows = MAX_INT;
- else if (is_scroll_word)
- bp->more_rows = zscrolln - bp->cols;
- else bp->more_rows = zscrolln;
- bp->reinit_browse = TRUE;
- break;
- case UP:
- if (is_max) bp->more_rows = -MAX_INT;
- else if (is_scroll_cursor)
- bp->more_rows = -zscrolln;
- else if (is_scroll_word)
- bp->more_rows = -zscrolln - bp->cols;
- else bp->more_rows = -zscrolln;
- bp->reinit_browse = TRUE;
- break;
- case LEFT:
- if (is_max) bp->coloff = 0;
- else bp->coloff -= zscrolln;
- if (bp->coloff < 0) bp->coloff = 0;
- *bp->cols_line = '\0';
- bp->more_rows = 0;
- bp->reinit_browse = TRUE;
- break;
- case RIGHT:
- if (is_max) bp->coloff = bp->maxcoloff;
- else bp->coloff += zscrolln;
- if (bp->coloff > bp->maxcoloff) bp->coloff = bp->maxcoloff;
- *bp->cols_line = '\0';
- bp->more_rows = 0;
- bp->reinit_browse = TRUE;
- break;
- }
- }
-
- return;
- }
-
- /****** View text in full screen mode (BROWSE replacement) ***********/
-
- void
- GGview(gp,ip,texthdrp,title)
- RGGCB *gp;
- RINFO *ip;
- TEXTHDR *texthdrp;
- char *title;
- {
- TEXTLINE *tp;
- TEXTLINE **tv;
- TEXTLINE **textvector;
- struct browser *bp;
- struct browser browserstruct;
-
- GETMAIN(textvector,TEXTLINE *,texthdrp->text_line_count,"text vector");
- if (!textvector) {
- ERR1("Not enough memory to display text.");
- return;
- }
-
- bp = &browserstruct;
- CLEAR(bp);
- bp->ip = ip;
- bp->thp = texthdrp;
- bp->tv = textvector;
- strcpy(bp->title,title);
- bp->more_rows = -MAX_INT; /* set initial request to scroll up max */
- bp->top = 0;
- bp->find_row = -1;
- bp->find_col = -1;
- bp->csrpos = 1;
- strcpy(bp->cursor,"");
- bp->reinit_browse = TRUE;
-
- /* Collect text line pointers, skipping suppressed lines. */
-
- bp->maxlen = 0;
- for (tp=texthdrp->first_text_line, tv=textvector; tp; tp=tp->next) {
- if (tp->text_length >= 0) {
- *(tv++) = tp;
- if (bp->maxlen < tp->tab_expanded_text_length)
- bp->maxlen = tp->tab_expanded_text_length;
- }
- }
- bp->maxcoloff = bp->maxlen - 80;
- if (bp->maxcoloff < 0) bp->maxcoloff = 0;
-
- GETMAIN(bp->work, char, bp->maxlen+1, "browse work string");
- if (!bp->work) return;
-
- ISPF("PQUERY PANEL(GGMVIEW) AREANAME(GGBDYNA) DEPTH(GGBDEPTH)");
- if (gp->ispfrc != 0) return;
- bp->depth = IGET("GGBDEPTH ");
- bp->size = bp->depth * 80;
- GETMAIN(bp->bda, char, bp->size+1, "browse dynamic area");
- if (!bp->bda) return;
-
- if (!gp->text_dispchar) gp->text_dispchar = '.';
-
- do {
- if (bp->reinit_browse) {
- fill_browse_dynamic_area(gp,bp);
- highlight_browse_text(gp,bp);
- }
- display_browse_data(gp,bp);
- } while (!gp->quit && !bp->exit_browse);
-
- FREEMAIN(bp->work,"browse work string");
- FREEMAIN(bp->bda, "browse dynamic area");
- FREEMAIN(textvector, "text vector");
-
- return;
- }
-
- ./ ADD NAME=GGVTX
-
- /********************************************************************/
- /* */
- /* Copyright (c) The Charles Stark Draper Laboratory, 1992, 1993 */
- /* GOPHER server due to Shawn Hart at the University of Delaware. */
- /* GOPHER client due to Steve Bacher at Draper Laboratory. */
- /* SAS modifications due to Dale Ingold at SAS Institute, Inc. */
- /* */
- /* This software is provided on an "AS IS" basis. All warranties, */
- /* including the implied warranties of merchantability and fitness, */
- /* are expressly denied. */
- /* */
- /* Provided this copyright notice is included, this software may */
- /* be freely distributed and not offered for sale. */
- /* */
- /* Changes or modifications may be made and used only by the maker */
- /* of same, and not further distributed. Such modifications should */
- /* be mailed to the author for consideration for addition to the */
- /* software and incorporation in subsequent releases. */
- /* */
- /********************************************************************/
-
- #pragma csect(code, "GG@VTX ")
- #pragma csect(static,"GG$VTX ")
- #include "gg.h"
-
- /****** View the lines of text retrieved from the server. ************/
-
- Bool
- GGvtx(gp,ip,how)
- RGGCB *gp;
- RINFO *ip;
- GOHOW how;
- {
- TEXTHDR *texthdrp;
- char title [81];
-
- switch (how) {
- case AS_NOTHING: return;
- default: break;
- }
-
- texthdrp = (ip ? &ip->thdr : &gp->thdr);
-
- if (!ip) sprintf(title, "GopherServer:%s ",gp->ggserver);
- else strncpy(title, ip->desc, sizeof(title));
-
- GGview(gp,ip,texthdrp,title);
-
- return;
- }
-
- ./ ADD NAME=GGWAIS
-
- /********************************************************************/
- /* */
- /* Copyright (c) The Charles Stark Draper Laboratory, 1992, 1993 */
- /* GOPHER server due to Shawn Hart at the University of Delaware. */
- /* GOPHER client due to Steve Bacher at Draper Laboratory. */
- /* SAS modifications due to Dale Ingold at SAS Institute, Inc. */
- /* */
- /* This software is provided on an "AS IS" basis. All warranties, */
- /* including the implied warranties of merchantability and fitness, */
- /* are expressly denied. */
- /* */
- /* Provided this copyright notice is included, this software may */
- /* be freely distributed and not offered for sale. */
- /* */
- /* Changes or modifications may be made and used only by the maker */
- /* of same, and not further distributed. Such modifications should */
- /* be mailed to the author for consideration for addition to the */
- /* software and incorporation in subsequent releases. */
- /* */
- /********************************************************************/
-
- #pragma csect(code, "GG@WAIS ")
- #pragma csect(static,"GG$WAIS ")
- #include "gg.h"
-
- /****** Gopher WAIS interface. *************************************/
-
- Bool
- GGwais(gp,ip,how)
- RGGCB *gp;
- RINFO *ip;
- GOHOW how;
- {
- RCONN *sp = &gp->gopher_connection;
- char *lp;
- char ggwaisq [256];
-
- strcpy(gp->ggserver,ip->host); /* Specify server to connect to */
- strcpy(ggwaisq,"");
- ISPF("VGET (GGWAISQ) PROFILE");
- if (GGdispl(gp,"GGMPWAIS") > 0) return FALSE;
- VGET("GGWAISQ ",ggwaisq);
-
- if (!*ip->path) strcpy(gp->gopher_command, ggwaisq);
- else sprintf(gp->gopher_command,"%s\t%s",ip->path,ggwaisq);
-
- gp->ginfo = ip;
-
- if (!GGconn(gp,sp)) return FALSE; /* Connect to gopher server */
- GOPHERSEND(gp,sp); /* Send socket command */
- GGclrtx(gp,ip); /* Clear text */
- sp->receiving_text = TRUE;
-
- while (GGgsrvl(gp,sp,&lp,CRLF)) { /* Get server line */
- if (!lp) break;
- (void)GGouttx(gp,lp,ip,NO_VALUE); /* Output text line */
- }
- if (sp->time_to_go_home) {
- WARN2("No data available from server %s.\n",gp->ggserver);
- return FALSE;
- }
-
- if (sp->connected_to_server) {
- (void)GGdisc(gp,sp); /* Disconnect from gopher server */
- }
-
- GGdir(gp,ip,how); /* display entries returned from WAIS server */
-
- return TRUE;
-
- }
-
- ./ ADD NAME=GGWHOIS
-
- /********************************************************************/
- /* */
- /* Copyright (c) The Charles Stark Draper Laboratory, 1992, 1993 */
- /* GOPHER server due to Shawn Hart at the University of Delaware. */
- /* GOPHER client due to Steve Bacher at Draper Laboratory. */
- /* SAS modifications due to Dale Ingold at SAS Institute, Inc. */
- /* */
- /* This software is provided on an "AS IS" basis. All warranties, */
- /* including the implied warranties of merchantability and fitness, */
- /* are expressly denied. */
- /* */
- /* Provided this copyright notice is included, this software may */
- /* be freely distributed and not offered for sale. */
- /* */
- /* Changes or modifications may be made and used only by the maker */
- /* of same, and not further distributed. Such modifications should */
- /* be mailed to the author for consideration for addition to the */
- /* software and incorporation in subsequent releases. */
- /* */
- /********************************************************************/
-
- #pragma csect(code, "GG@WHOIS")
- #pragma csect(static,"GG$WHOIS")
- #include "gg.h"
-
- /****** Gopher WHOIS/FINGER interface. *****************************/
-
- Bool
- GGwhois(gp,ip,how)
- RGGCB *gp;
- RINFO *ip;
- GOHOW how;
- {
- RCONN *sp = &gp->gopher_connection;
- char *lp;
- Bool got_some;
- char ggwhoisq [256];
-
- strcpy(gp->ggserver,ip->host); /* Specify server to connect to */
- strcpy(ggwhoisq,"");
- ISPF("VGET (GGWHOISQ) PROFILE");
- if (GGdispl(gp,"GGMPWHOI") > 0) return FALSE;
- VGET("GGWHOISQ ",ggwhoisq);
-
- if (!*ip->path) strcpy(gp->gopher_command, ggwhoisq);
- else sprintf(gp->gopher_command,"%s\t%s",ip->path,ggwhoisq);
-
- gp->ginfo = ip;
-
- if (!GGconn(gp,sp)) return FALSE; /* Connect to gopher server */
- GOPHERSEND(gp,sp); /* Send socket command */
- GGclrtx(gp,ip); /* Clear text */
-
- sp->receiving_text = TRUE;
- got_some = FALSE;
- while (GGgsrvl(gp,sp,&lp,CRLF)) { /* Get server line */
- if (!lp) break;
- got_some = TRUE;
- (void)GGouttx(gp,lp,ip,NO_VALUE); /* Output text line */
- }
-
- if (!got_some) {
- WARN2("No data available from server %s.\n",gp->ggserver);
- return FALSE;
- }
-
- if (sp->connected_to_server) {
- (void)GGdisc(gp,sp); /* Disconnect from gopher server */
- }
-
- GGvtx(gp,ip,how); /* display text from WHOIS/FINGER server */
-
- return TRUE;
-
- }
-
- ./ ADD NAME=GGWTO
-
- /********************************************************************/
- /* */
- /* Copyright (c) The Charles Stark Draper Laboratory, 1992, 1993 */
- /* */
- /* This software is provided on an "AS IS" basis. All warranties, */
- /* including the implied warranties of merchantability and fitness, */
- /* are expressly denied. */
- /* */
- /* Provided this copyright notice is included, this software may */
- /* be freely distributed and not offered for sale. */
- /* */
- /* Changes or modifications may be made and used only by the maker */
- /* of same, and not further distributed. Such modifications should */
- /* be mailed to the author for consideration for addition to the */
- /* software and incorporation in subsequent releases. */
- /* */
- /********************************************************************/
-
- #pragma csect(code, "GG@WTO")
- #pragma csect(static,"GG$WTO")
-
- #include "gg.h"
- #include "ggsvc.h"
-
- #define WTOTEXTLENGTH 256
- #define WTOSVC 35
-
- #define WRITE_TO_PROGRAMMER 1
-
- int
- GGwto(char *message)
- {
- char *cp;
- SVC_REGISTER reg15;
- SVC_REGISTER reg0;
- SVC_REGISTER reg1;
- struct {
- short wtolen;
- short wtodum;
- char wtotext[WTOTEXTLENGTH+1];
- char routecodestuff[9];
- } wto;
-
- CLEAR(&wto);
- strncpy(wto.wtotext,message,WTOTEXTLENGTH);
- wto.wtolen = strlen(wto.wtotext) + 4;
- wto.wtodum = 0;
-
- #ifdef WRITE_TO_PROGRAMMER
-
- wto.wtodum = 0x8000;
- cp = wto.wtotext + strlen(wto.wtotext);
- cp[0] = 0x00;
- cp[1] = 0x00;
- cp[2] = 0x00;
- cp[3] = 0x20;
-
- #else
-
- wto.wtodum = 0;
-
- #endif
-
-
- reg15 = (SVC_REGISTER) 0;
- reg0 = (SVC_REGISTER) 0;
- reg1 = (SVC_REGISTER) &wto;
-
- SVC(WTOSVC,®15,®0,®1);
-
- return (int)reg15;
-
- }
-
- ./ ADD NAME=GGXTX
-
- /********************************************************************/
- /* */
- /* Copyright (c) The Charles Stark Draper Laboratory, 1992, 1993 */
- /* GOPHER server due to Shawn Hart at the University of Delaware. */
- /* GOPHER client due to Steve Bacher at Draper Laboratory. */
- /* SAS modifications due to Dale Ingold at SAS Institute, Inc. */
- /* */
- /* This software is provided on an "AS IS" basis. All warranties, */
- /* including the implied warranties of merchantability and fitness, */
- /* are expressly denied. */
- /* */
- /* Provided this copyright notice is included, this software may */
- /* be freely distributed and not offered for sale. */
- /* */
- /* Changes or modifications may be made and used only by the maker */
- /* of same, and not further distributed. Such modifications should */
- /* be mailed to the author for consideration for addition to the */
- /* software and incorporation in subsequent releases. */
- /* */
- /********************************************************************/
-
- #pragma csect(code, "GG@XTX ")
- #pragma csect(static,"GG$XTX ")
- #include "gg.h"
-
- #define XFPUTC(A) gp->extract_write_error = (fputc((A),xfp) == EOF)
-
- #define XFWRITE(A,B) fwrite((A),(B),1,xfp), \
- gp->extract_write_error = (ferror(xfp) != 0)
- #define XWRITE(A) XFWRITE(A,strlen(A))
-
- #define NEWLINE if (ex != BOOKMANAGE_IT) XFPUTC('\n')
-
- /****** Extract the lines of server text into a data set. ************/
-
- Bool
- GGxtx(gp,ip,ex)
- RGGCB *gp;
- RINFO *ip;
- EXTREQ ex;
- {
- FILE *xfp;
- TEXTHDR *thp;
- TEXTLINE *tp;
- EXTRACTION *ep;
- char *cp;
- int l;
- int linelen;
- Bool final;
- EXTRACTION the_extraction;
-
- thp = (ip && ex != BOOKMARK_IT ? &ip->thdr : &gp->thdr);
-
- /* Set article data for message. */
-
- if (ip) {
- IPUT("GGTNUM " ,ip->type);
- VPUT("GGTSUBJ ",ip->desc);
- }
-
- if (ex == BOOKMANAGE_IT) {
- xfp = gp->extract_file;
- ep = &the_extraction;
- CLEAR(ep);
- ep->ex = ex;
- gp->extract_tab_expanding = ep->tab_expanding;
- gp->extract_appending = ep->appending;
- gp->extract_blank_before_separator = ep->blanking;
- gp->extract_separator_line = ep->separator;
- }
- else if (gp->extract_file) {
- ISPF("CONTROL DISPLAY LOCK");
- switch (ex) {
- case PRINT_IT: ISPF("DISPLAY PANEL(GGMLPRN2)"); break;
- default: ISPF("DISPLAY PANEL(GGMLEXN2)"); break;
- }
- xfp = gp->extract_file;
- ep = gp->extractionp;
- }
- else {
-
- ep = &the_extraction;
- CLEAR(ep);
- switch (ex) {
- case EXTRACT_IT: ep->mode = SEQ;
- strcpy(ep->panelname,"GGMPEXDS");
- break;
- case PRINT_IT: ep->mode = JES;
- strcpy(ep->panelname,"GGMPPRDS");
- break;
- case BOOKMARK_IT: ep->mode = SEQ;
- strcpy(ep->panelname,"GGMPBMDS");
- break;
- }
- ep->ex = ex;
-
- if (ip) VPUT("GGTSUBJ ",ip->desc);
- else VPUT("GGTSUBJ ","");
-
- if (!((xfp=GGgetds(gp,ep)))) return FALSE;
-
- gp->extract_tab_expanding = ep->tab_expanding;
- gp->extract_appending = ep->appending;
- gp->extract_blank_before_separator = ep->blanking;
- gp->extract_separator_line = ep->separator;
- }
-
- gp->extract_write_error = FALSE;
- gp->extract_close_error = FALSE;
-
- /* If a bookmark, then write gopher menu header only if this is
- * a new data set (not appending).
- */
-
- if (ep->ex == BOOKMARK_IT && !ep->appending) {
- XWRITE(MENUIDENT);
- NEWLINE;
- }
-
- /* If append mode, and a separator line was specified, use it. */
-
- if (gp->extract_appending) {
- NEWLINE;
- if (gp->extract_separator_line && *gp->extract_separator_line) {
- XWRITE(gp->extract_separator_line);
- NEWLINE;
- if (gp->extract_blank_before_separator) {NEWLINE;}
- }
- }
-
- switch (ex) {
- case EXTRACT_IT: linelen = 251; break;
- case PRINT_IT: linelen = 120; break;
- case BOOKMARK_IT: linelen = 251; break;
- case BOOKMANAGE_IT: linelen = 4096; break;
- }
-
- for (tp = thp->first_text_line;
- tp && !gp->extract_write_error;
- tp = tp->next) {
- if (tp->text_length == 0) {
- NEWLINE;
- }
- else if (tp->text_length > 0) {
- if (gp->extract_tab_expanding) {
- cp = tp->tab_expanded_text;
- l = tp->tab_expanded_text_length;
- }
- else {
- cp = tp->text;
- l = tp->text_length;
- }
- for (; l>0 && !gp->extract_write_error; cp+=linelen, l-=linelen) {
- XFWRITE(cp,(l > linelen ? linelen : l));
- NEWLINE;
- }
- }
- }
-
- if (!gp->extract_write_error && ferror(xfp))
- gp->extract_write_error = TRUE;
-
- if (ex != BOOKMANAGE_IT) {
- if (!gp->extract_appending || !gp->extract_file) {
- switch (ex) {
- case PRINT_IT: final = TRUE; break;
- default: final = FALSE; break;
- }
- (ep->closer)(gp,ep,xfp,final); /* Close the file */
- if (gp->extract_close_error) return FALSE;
- }
- }
-
- if (!gp->extract_file) {
- if (gp->extract_write_error) {
- ERR2("An error occurred writing to %s.", ep->dsname);
- gp->extract_write_error = TRUE;
- }
- else switch (ex) {
- case EXTRACT_IT:
- WARN2("Current text extracted into %s.", ep->dsname);
- break;
- case PRINT_IT:
- WARN2("Current text printed to %s.", ep->dsname);
- break;
- case BOOKMARK_IT:
- WARN2("Item stored as bookmark in %s.", ep->dsname);
- break;
- }
- }
- if (gp->extract_write_error) return FALSE;
- else return TRUE;
- }
-
- ./ ADD NAME=XGALLOC
-
- /********************************************************************/
- /* */
- /* Copyright (c) The Charles Stark Draper Laboratory, 1992, 1993 */
- /* */
- /* This software is provided on an "AS IS" basis. All warranties, */
- /* including the implied warranties of merchantability and fitness, */
- /* are expressly denied. */
- /* */
- /* Provided this copyright notice is included, this software may */
- /* be freely distributed and not offered for sale. */
- /* */
- /* Changes or modifications may be made and used only by the maker */
- /* of same, and not further distributed. Such modifications should */
- /* be mailed to the author for consideration for addition to the */
- /* software and incorporation in subsequent releases. */
- /* */
- /********************************************************************/
-
- /*
- ***********************************************************************
- * *
- * This is not a main program, nor a subroutine to be linked into an *
- * existing program, but a routine which is to be called from a *
- * REXX exec as follows: *
- * *
- * dsn = "name.of.data.set" -- or null to create a temporary *
- * dnn = "ddname" -- or null to generate a unique one *
- * disp = "SHR" -- or "OLD", "NEW", "FREE" or "DELETE" *
- * msg1 = "" -- to be set with an error message *
- * msg2 = "" -- to be set with an error message *
- * *
- * address LINKMVS "XGALLOC DSN DDN DISP MSG1 MSG2" *
- * *
- * In addition to possibly updating the indicated variables, this *
- * routine returns a return code, which becomes the value of "RC". *
- * *
- * The purpose of this routine is to provide a way for REXX execs *
- * to perform allocation and unallocation of data sets from a non-TSO *
- * environment. The LINKMVS (or ATTCHMVS) interface allows it to *
- * update the specified REXX variables by setting values for the *
- * passed parameters without calling REXX routines directly. *
- * *
- * Use of this routine requires TSO/REXX 3.46 or higher. *
- * *
- ***********************************************************************
- */
-
- #pragma environment(XGALLOC)
- #pragma linkage(ikjeff18,OS)
-
- #include "gg.h"
- #include "ggsvc.h"
- #include "ggsvc99.h"
-
- #include <spc.h>
-
- enum disposition {DISP_SHR,DISP_OLD,DISP_MOD,
- DISP_NEW,DISP_KEEP,DISP_DELETE};
-
- #define set2(A,B) *(short *)(A) = B
- #define set3(A,B) memset(A,0,3); *(short *)(A+1) = B
-
- struct varstring {
- short len;
- char text[1];
- };
-
- typedef struct varstring VARSTRING;
- typedef int (*ENTRYPOINT) ();
-
- /*--------------------------------------------------------------------*/
-
- static ENTRYPOINT
- ggload(char *module)
- {
- char eploc[9];
- SVC_REGISTER reg15;
- SVC_REGISTER reg0;
- SVC_REGISTER reg1;
-
- #define LOAD_SVC 8
-
- memset(eploc,' ',8);
- memcpy(eploc,module,strlen(module));
-
- reg15 = (SVC_REGISTER) 0;
- reg0 = (SVC_REGISTER) &eploc;
- reg1 = (SVC_REGISTER) 0;
-
- SVC(LOAD_SVC,®15,®0,®1);
-
- return (ENTRYPOINT)reg0;
-
- }
-
- /*--------------------------------------------------------------------*/
-
- static void
- allocfail(rc,p99,msg1,msg2)
- int rc;
- __S99parms *p99;
- char *msg1;
- char *msg2;
- {
- int zero = 0;
- unsigned int dfid = 0x40320000;
- struct {
- short first_level_msg_len;
- short first_level_msg_offset;
- char first_level_msg[251];
- short second_level_msg_len;
- short second_level_msg_offset;
- char second_level_msg[251];
- } dfbuffer;
-
- static ENTRYPOINT ikjeff18_pointer = NULL;
-
- strcpy(msg1,"");
- strcpy(msg2,"");
-
- if (!ikjeff18_pointer) {
- ikjeff18_pointer = ggload("IKJEFF18");
- }
-
- dfbuffer.first_level_msg_len = 4;
- dfbuffer.second_level_msg_len = 4;
-
- if (ikjeff18_pointer) {
- if ((*ikjeff18_pointer)(p99,&rc,&zero,&dfid,&zero,&dfbuffer)) {
- strcpy(msg1,"IKJEFF18 returned a nonzero return code");
- }
- if (dfbuffer.first_level_msg_len > 0) {
- strncpy(msg1, dfbuffer.first_level_msg,
- dfbuffer.first_level_msg_len-4);
- }
- if (dfbuffer.second_level_msg_len > 0) {
- strncpy(msg2, dfbuffer.second_level_msg,
- dfbuffer.second_level_msg_len-4);
- }
- }
- else {
- strcpy(msg1,"XGALLOC cannot load IKJEFF18");
- }
- return;
- }
-
- /*--------------------------------------------------------------------*/
-
- static void
- setmsg(msgvar,string)
- VARSTRING *msgvar;
- char *string;
- {
-
- msgvar->len = strlen(string);
- memcpy(msgvar->text,string,msgvar->len);
- return;
- }
-
- /*--------------------------------------------------------------------*/
-
- int
- XGALLOC()
- {
- VARSTRING **reg1;
- VARSTRING *dsnvar;
- VARSTRING *ddnvar;
- VARSTRING *dispvar;
- VARSTRING *msg1var;
- VARSTRING *msg2var;
- int i;
- int rc;
- int disp99_1;
- int disp99_2;
- Bool unal;
- enum disposition disp;
- short primary_allocation = 0;
- short secondary_allocation = 0;
- short directory_blocks = 0;
- short dsorg = 0;
- char recfm = 0;
- short lrecl = 0;
- short blocksize = 0;
- __S99parms stuff99; /* No "struct", despite manual */
- TEXTUNIT *return_dsname_tup = NULL;
- TEXTUNIT *return_ddname_tup = NULL;
- TEXTUNIT *tup [32];
- TEXTUNIT tu [32];
- char *lparp;
- char *rparp;
- char dsname [81];
- char ddname [9];
- char dispname [9];
- char member [81];
- char msg1 [256];
- char msg2 [256];
-
- reg1 = (VARSTRING **)edcxregs(1);
-
- dsnvar = reg1[0];
- ddnvar = reg1[1];
- dispvar = reg1[2];
- msg1var = reg1[3];
- msg2var = reg1[4];
-
- memset((char *)&stuff99,0,sizeof(__S99parms));
- strcpy(msg1,"");
- strcpy(msg2,"");
-
- if (dsnvar->len > 56) {
- setmsg(msg1var,"DSNAME argument cannot be longer than 56");
- return 16;
- }
- if (ddnvar->len > 8) {
- setmsg(msg1var,"DDNAME argument cannot be longer than 8");
- return 16;
- }
- if (dispvar->len > 8) {
- setmsg(msg1var,"DISP must be SHR/OLD/MOD/NEW/FREE/KEEP/DELETE");
- return 16;
- }
-
- strncpy(dsname,dsnvar->text,dsnvar->len);
- strncpy(ddname,ddnvar->text,ddnvar->len);
- strncpy(dispname,dispvar->text,dispvar->len);
- uppercase_in_place(dsname);
- uppercase_in_place(ddname);
- uppercase_in_place(dispname);
-
- if (!strcmp(dispname,"SHR")) disp = DISP_SHR;
- else if (!strcmp(dispname,"OLD")) disp = DISP_OLD;
- else if (!strcmp(dispname,"MOD")) disp = DISP_MOD;
- else if (!strcmp(dispname,"NEW")) disp = DISP_NEW;
- else if (!strcmp(dispname,"FREE")) disp = DISP_KEEP;
- else if (!strcmp(dispname,"KEEP")) disp = DISP_KEEP;
- else if (!strcmp(dispname,"DELETE")) disp = DISP_DELETE;
- else {
- setmsg(msg1var,"DISP must be SHR/OLD/MOD/NEW/FREE/KEEP/DELETE");
- return 16;
- }
-
- switch (disp) {
- case DISP_SHR: unal=FALSE; disp99_1=SHR; disp99_2=KEEP; break;
- case DISP_OLD: unal=FALSE; disp99_1=OLD; disp99_2=KEEP; break;
- case DISP_MOD: unal=FALSE; disp99_1=MOD; disp99_2=CATLG; break;
- case DISP_NEW: unal=FALSE; disp99_1=NEW; disp99_2=CATLG; break;
- case DISP_KEEP: unal=TRUE; disp99_2=KEEP; break;
- case DISP_DELETE: unal=TRUE; disp99_2=DELETE; break;
- }
-
- switch (disp) {
- case DISP_MOD:
- case DISP_NEW:
- primary_allocation = 100;
- secondary_allocation = primary_allocation;
- dsorg = DSORG_PS;
- recfm = RECFM_VB;
- lrecl = 256;
- blocksize = 23440;
- break;
- }
-
- strcpy(member,"");
- lparp = strchr(dsname,'(');
- rparp = strchr(dsname,')');
- if (lparp && rparp && (lparp < rparp) && (*(rparp+1) == '\0')) {
- *lparp = '\0'; /* makes dsname the seq part only */
- *rparp = '\0'; /* turns member into a string */
- strcpy(member, lparp+1);
- }
-
- stuff99.__S99RBLN = 20;
- stuff99.__S99VERB = unal ? S99VRBUN : S99VRBAL;
- stuff99.__S99FLAG1 = S99NOCNV << 8;
- stuff99.__S99ERROR = 0;
- stuff99.__S99INFO = 0;
- stuff99.__S99TXTPP = tup;
- stuff99.__S99FLAG2 = 0;
-
- for (i=0; i<32; i++) tup[i] = &tu[i];
-
- i = 0;
-
- if (*dsname) {
- tu[i].key = unal ? DUNDSNAM : DALDSNAM;
- tu[i].num = 1;
- tu[i].ent.len = strlen(dsname);
- copy_uppercase(tu[i].ent.prm,dsname);
- i++;
- }
- else if (!unal) {
- tu[i].key = DALRTDSN;
- tu[i].num = 1;
- tu[i].ent.len = 44;
- memset(tu[i].ent.prm,' ',44);
- return_dsname_tup = &tu[i];
- i++;
- }
- if (*member) {
- tu[i].key = DALMEMBR;
- tu[i].num = 1;
- tu[i].ent.len = strlen(member);
- copy_uppercase(tu[i].ent.prm,member);
- i++;
- }
- if (*ddname) {
- tu[i].key = unal ? DUNDDNAM : DALDDNAM;
- tu[i].num = 1;
- tu[i].ent.len = strlen(ddname);
- copy_uppercase(tu[i].ent.prm,ddname);
- i++;
- if (!unal) {
- tu[i].key = DALPERMA;
- tu[i].num = 0;
- i++;
- }
- }
- else if (!unal) {
- tu[i].key = DALRTDDN;
- tu[i].num = 1;
- tu[i].ent.len = 8;
- memset(tu[i].ent.prm,' ',8);
- return_ddname_tup = &tu[i];
- i++;
- }
- if (unal) {
- tu[i].key = DUNUNALC;
- tu[i].num = 0;
- i++;
- }
- else {
- tu[i].key = DALSTATS;
- tu[i].num = 1;
- tu[i].ent.len = 1;
- tu[i].ent.prm[0] = disp99_1;
- i++;
- tu[i].key = DALNDISP;
- tu[i].num = 1;
- tu[i].ent.len = 1;
- tu[i].ent.prm[0] = disp99_2;
- i++;
- }
- if (recfm) {
- tu[i].key = DALRECFM;
- tu[i].num = 1;
- tu[i].ent.len = 1;
- tu[i].ent.prm[0] = recfm;
- i++;
- }
- if (lrecl) {
- tu[i].key = DALLRECL;
- tu[i].num = 1;
- tu[i].ent.len = 2;
- set2(tu[i].ent.prm,lrecl);
- i++;
- }
- if (blocksize) {
- tu[i].key = DALBLKSZ;
- tu[i].num = 1;
- tu[i].ent.len = 2;
- set2(tu[i].ent.prm,blocksize);
- i++;
- }
- if (blocksize) {
- tu[i].key = DALBLKLN;
- tu[i].num = 1;
- tu[i].ent.len = 3;
- set3(tu[i].ent.prm,blocksize);
- i++;
- }
- if (primary_allocation) {
- tu[i].key = DALPRIME;
- tu[i].num = 1;
- tu[i].ent.len = 3;
- set3(tu[i].ent.prm,primary_allocation);
- i++;
- }
- if (secondary_allocation) {
- tu[i].key = DALSECND;
- tu[i].num = 1;
- tu[i].ent.len = 3;
- set3(tu[i].ent.prm,secondary_allocation);
- i++;
- }
- if (dsorg) {
- tu[i].key = DALDSORG;
- tu[i].num = 1;
- tu[i].ent.len = 2;
- set2(tu[i].ent.prm,dsorg);
- i++;
- }
-
- tup[i] = (void *)0x80000000;
-
- rc = svc99(&stuff99);
-
- if (rc == 0) {
- if (return_dsname_tup) {
- memcpy(dsnvar->text,(char *)return_dsname_tup->ent.prm,64);
- dsnvar->len = return_dsname_tup->ent.len;
- }
- if (return_ddname_tup) {
- memcpy(ddnvar->text,(char *)return_ddname_tup->ent.prm,8);
- ddnvar->len = return_ddname_tup->ent.len;
- }
- }
- else {
- allocfail(rc,&stuff99,msg1,msg2);
- }
- setmsg(msg1var,msg1);
- setmsg(msg2var,msg2);
- return rc;
- }
-
- ./ ADD NAME=XGSLEEP
-
- /********************************************************************/
- /* */
- /* Copyright (c) The Charles Stark Draper Laboratory, 1992, 1993 */
- /* */
- /* This software is provided on an "AS IS" basis. All warranties, */
- /* including the implied warranties of merchantability and fitness, */
- /* are expressly denied. */
- /* */
- /* Provided this copyright notice is included, this software may */
- /* be freely distributed and not offered for sale. */
- /* */
- /* Changes or modifications may be made and used only by the maker */
- /* of same, and not further distributed. Such modifications should */
- /* be mailed to the author for consideration for addition to the */
- /* software and incorporation in subsequent releases. */
- /* */
- /********************************************************************/
-
- #include <stdio.h>
- #include "gg.h"
-
- main(int argc, char **argv) {
- int seconds = 0;
-
- if (argc > 1) seconds = atoi(argv[1]);
-
- if (seconds == 0) seconds = 1;
-
- return GGsleep(seconds);
-
- }
-
- ./ ADD NAME=XGWTO
-
- /********************************************************************/
- /* */
- /* Copyright (c) The Charles Stark Draper Laboratory, 1992, 1993 */
- /* */
- /* This software is provided on an "AS IS" basis. All warranties, */
- /* including the implied warranties of merchantability and fitness, */
- /* are expressly denied. */
- /* */
- /* Provided this copyright notice is included, this software may */
- /* be freely distributed and not offered for sale. */
- /* */
- /* Changes or modifications may be made and used only by the maker */
- /* of same, and not further distributed. Such modifications should */
- /* be mailed to the author for consideration for addition to the */
- /* software and incorporation in subsequent releases. */
- /* */
- /********************************************************************/
-
- #pragma runopts(noargparse,noredir)
-
- #include <stdio.h>
- #include "gg.h"
-
- main(int argc, char **argv) {
- char *message;
-
- if (argc < 2) message = "(No message)";
- else message = argv[1];
-
- return GGwto(message);
-
- }
-
- ./ ENDUP
- ?!
- //PANELS EXEC MDLOAD,BS='6160',TRK1='5',TRK2='1',TO='PANELS'
- //SYSIN DD DATA,DLM='?!'
- ./ ADD NAME=GGM
- )ATTR
- /* /*
- /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 /*
- /* /*
- /* This software is provided on an "AS IS" basis. All warranties, /*
- /* including the implied warranties of merchantability and fitness, /*
- /* are expressly denied. /*
- /* /*
- /* Provided this copyright notice is included, this software may /*
- /* be freely distributed and not offered for sale. /*
- /* /*
- /* Changes or modifications may be made and used only by the maker /*
- /* of same, and not further distributed. Such modifications should /*
- /* be mailed to the author for consideration for addition to the /*
- /* software and incorporation in subsequent releases. /*
- /* /*
- ^ TYPE(INPUT) INTENS(HIGH) COLOR(GREEN) CAPS(OFF)
- ! TYPE(TEXT) INTENS(HIGH) COLOR(RED)
- )BODY EXPAND(``)
- %-`-`- MVS Gopher Client -`-`-
- %COMMAND ===>_ZCMD
- +
- %Gopher server host name+(or IP address) %===>_GGHOST
- +
- %Initial path%===>^GGPATH
- %Port number %===>_GGPORT
- +
- +Note: You may specify a dash%-+as the Gopher server host name if
- you want to use your own private Gopher data without making
- a connection to a server. If you do, you must specify the
- name of your private Gopher menu in the initial path.
- This name must be UNQUOTED AND FULLY QUALIFIED.
- Alternatively, you may allocate your initial Gopher menu
- to file GGGOPHER.
-
- Any menu entries must also specify a dash in the host field;
- otherwise they will require server access, as usual.
-
- To use the REXX interface, you must allocate file GGEXEC to
- your library of Gopherable REXX execs.
-
- +Press!END+key to leave this menu.
- )INIT
- &ZCMD = &Z
- IF (&GGPORT = &Z) &GGPORT = 70
- )PROC
- IF (&ZCMD ^= &Z) .MSG = ISPZ001
- VER (&GGHOST,NB)
- VER (&GGPORT,NUM)
- VPUT (GGHOST GGPATH GGPORT) PROFILE
- )END
- ./ ADD NAME=GGMCSO
- )ATTR
- /* /*
- /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 /*
- /* /*
- /* This software is provided on an "AS IS" basis. All warranties, /*
- /* including the implied warranties of merchantability and fitness, /*
- /* are expressly denied. /*
- /* /*
- /* Provided this copyright notice is included, this software may /*
- /* be freely distributed and not offered for sale. /*
- /* /*
- /* Changes or modifications may be made and used only by the maker /*
- /* of same, and not further distributed. Such modifications should /*
- /* be mailed to the author for consideration for addition to the /*
- /* software and incorporation in subsequent releases. /*
- /* /*
- ^ TYPE(INPUT) INTENS(HIGH) CAPS(OFF) JUST(LEFT)
- @ TYPE(OUTPUT) INTENS(HIGH) CAPS(OFF) JUST(LEFT)
- )BODY
- +
- %Command ===>^ZCMD
- +
- +Enter name to search for:
- +
- @FNAME1 +==>^FVALUE1
- @FNAME2 +==>^FVALUE2
- @FNAME3 +==>^FVALUE3
- @FNAME4 +==>^FVALUE4
- @FNAME5 +==>^FVALUE5
- @FNAME6 +==>^FVALUE6
- @FNAME7 +==>^FVALUE7
- @FNAME8 +==>^FVALUE8
- @FNAME9 +==>^FVALUE9
- @FNAME10 +==>^FVALUE10
- @FNAME11 +==>^FVALUE11
- @FNAME12 +==>^FVALUE12
- @FNAME13 +==>^FVALUE13
- @FNAME14 +==>^FVALUE14
-
- +Press%ENTER+to submit search request.
- +Press%&END (END)+to cancel the request.
- +
- )INIT
- &ZWINTTL = 'CSO Nameserver User Name Search'
- &END = PFK(END)
- .CURSOR = FVALUE1
- )PROC
- IF (&ZCMD ^= &Z) .MSG = ISPZ001
- VPUT (FVALUE1 FVALUE2 FVALUE3 FVALUE4 FVALUE5 FVALUE6 FVALUE7) PROFILE
- VPUT (FVALUE8 FVALUE9 FVALUE10 FVALUE11 FVALUE12) PROFILE
- VPUT (FVALUE13 FVALUE14) PROFILE
- )END
- ./ ADD NAME=GGMDIR
- )ATTR
- /* /*
- /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 /*
- /* /*
- /* This software is provided on an "AS IS" basis. All warranties, /*
- /* including the implied warranties of merchantability and fitness, /*
- /* are expressly denied. /*
- /* /*
- /* Provided this copyright notice is included, this software may /*
- /* be freely distributed and not offered for sale. /*
- /* /*
- /* Changes or modifications may be made and used only by the maker /*
- /* of same, and not further distributed. Such modifications should /*
- /* be mailed to the author for consideration for addition to the /*
- /* software and incorporation in subsequent releases. /*
- /* /*
- ~ TYPE(INPUT) INTENS(HIGH) CAPS(OFF) JUST(LEFT)
- ^ TYPE(INPUT) INTENS(HIGH) CAPS(OFF) JUST(LEFT)
- ! TYPE(OUTPUT) INTENS(LOW) CAPS(OFF) JUST(RIGHT) COLOR(YELLOW)
- # TYPE(OUTPUT) INTENS(LOW) CAPS(OFF) JUST(RIGHT) COLOR(BLUE)
- @ TYPE(OUTPUT) INTENS(HIGH) CAPS(OFF) JUST(RIGHT) COLOR(PINK)
- ? TYPE(OUTPUT) INTENS(LOW) CAPS(OFF) JUST(LEFT) COLOR(TURQ) PAD('.')
- | AREA(DYNAMIC) EXTEND(ON) SCROLL(ON)
- \ AREA(DYNAMIC) EXTEND(OFF) SCROLL(OFF)
- 01 TYPE(DATAOUT) INTENS(LOW)
- 02 TYPE(DATAOUT) INTENS(HIGH)
- 03 TYPE(DATAIN) INTENS(LOW)
- 04 TYPE(DATAIN) INTENS(HIGH)
- 05 TYPE(DATAOUT) COLOR(GREEN)
- 06 TYPE(DATAOUT) COLOR(PINK)
- 07 TYPE(DATAOUT) COLOR(RED)
- 08 TYPE(DATAOUT) COLOR(TURQ)
- 09 TYPE(DATAOUT) COLOR(YELLOW)
- 0A TYPE(DATAIN) COLOR(BLUE)
- 0B TYPE(DATAIN) COLOR(PINK)
- 0C TYPE(DATAIN) COLOR(TURQ)
- 0D TYPE(DATAIN) COLOR(WHITE)
- 0E TYPE(DATAIN) COLOR(YELLOW)
- )BODY EXPAND(``)
- %&GGGHEAD
- %COMMAND ===>~GGGCMD %SCROLL ===>^GAMT+
- +
- +%S+Select%Q+Query%E+Extract%P+Print%B+Bookmark%I+Info
- -------------------------------------------------------------------------------
- |GGGDYNA |
- )INIT
- IF (&GAMT = &Z) &GAMT = CSR
- IF (&GGGCSR ^= 0)
- .CURSOR = GGGDYNA
- .CSRPOS = &GGGCSR
- )PROC
- &GGGLVL = LVLINE(GGGDYNA)
- VPUT (GAMT) PROFILE
- )END
- ./ ADD NAME=GGMLCONN
- )ATTR
- /* /*
- /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 /*
- /* /*
- /* This software is provided on an "AS IS" basis. All warranties, /*
- /* including the implied warranties of merchantability and fitness, /*
- /* are expressly denied. /*
- /* /*
- /* Provided this copyright notice is included, this software may /*
- /* be freely distributed and not offered for sale. /*
- /* /*
- /* Changes or modifications may be made and used only by the maker /*
- /* of same, and not further distributed. Such modifications should /*
- /* be mailed to the author for consideration for addition to the /*
- /* software and incorporation in subsequent releases. /*
- /* /*
- ^ TYPE(TEXT) INTENS(HIGH) COLOR(BLUE) HILITE(REVERSE)
- @ TYPE(TEXT) INTENS(HIGH) COLOR(PINK)
- # TYPE(TEXT) INTENS(LOW) COLOR(TURQ)
- \ TYPE(TEXT) INTENS(HIGH) COLOR(YELLOW)
- ! TYPE(TEXT) INTENS(HIGH) COLOR(RED)
- $ TYPE(TEXT) INTENS(LOW) COLOR(GREEN)
- ~ TYPE(TEXT) INTENS(HIGH) COLOR(WHITE)
- )BODY EXPAND(``)
- %-`-`- MVS Gopher Server Connection -`-`-
- +
- + Client name: &CLIENT
- +
- +
- + Connection is in progress for Gopher server at:
- &SERVER
- +
- +
- % Please wait.
- +
- +
- )INIT
- &CLIENT = '&GGCLIENT (&GGCLIEIP)'
- &SERVER = '&GGSERVER (&GGSERVIP)'
- )PROC
- )END
- ./ ADD NAME=GGMLDISC
- )ATTR
- /* /*
- /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 /*
- /* /*
- /* This software is provided on an "AS IS" basis. All warranties, /*
- /* including the implied warranties of merchantability and fitness, /*
- /* are expressly denied. /*
- /* /*
- /* Provided this copyright notice is included, this software may /*
- /* be freely distributed and not offered for sale. /*
- /* /*
- /* Changes or modifications may be made and used only by the maker /*
- /* of same, and not further distributed. Such modifications should /*
- /* be mailed to the author for consideration for addition to the /*
- /* software and incorporation in subsequent releases. /*
- /* /*
- ^ TYPE(TEXT) INTENS(HIGH) COLOR(BLUE) HILITE(REVERSE)
- @ TYPE(TEXT) INTENS(HIGH) COLOR(PINK)
- # TYPE(TEXT) INTENS(LOW) COLOR(TURQ)
- \ TYPE(TEXT) INTENS(HIGH) COLOR(YELLOW)
- ! TYPE(TEXT) INTENS(HIGH) COLOR(RED)
- $ TYPE(TEXT) INTENS(LOW) COLOR(GREEN)
- ~ TYPE(TEXT) INTENS(HIGH) COLOR(WHITE)
- )BODY EXPAND(``)
- %-`-`- MVS Gopher Server Connection -`-`-
- +
- +
- + Disconnection is in progress from the Gopher server at:
- &GGSOLDER (&GGSOLDIP)
- +
- +
- % Please wait.
- +
- +
- )INIT
- )PROC
- )END
- ./ ADD NAME=GGMLEXN2
- )ATTR
- /* /*
- /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 /*
- /* /*
- /* This software is provided on an "AS IS" basis. All warranties, /*
- /* including the implied warranties of merchantability and fitness, /*
- /* are expressly denied. /*
- /* /*
- /* Provided this copyright notice is included, this software may /*
- /* be freely distributed and not offered for sale. /*
- /* /*
- /* Changes or modifications may be made and used only by the maker /*
- /* of same, and not further distributed. Such modifications should /*
- /* be mailed to the author for consideration for addition to the /*
- /* software and incorporation in subsequent releases. /*
- /* /*
- ^ TYPE(TEXT) INTENS(HIGH) COLOR(BLUE) HILITE(REVERSE)
- @ TYPE(TEXT) INTENS(HIGH) COLOR(PINK)
- \ TYPE(TEXT) INTENS(HIGH) COLOR(YELLOW)
- ! TYPE(TEXT) INTENS(HIGH) COLOR(RED)
- $ TYPE(TEXT) INTENS(LOW) COLOR(GREEN)
- ~ TYPE(TEXT) INTENS(HIGH) COLOR(WHITE)
- )BODY EXPAND(``)
- %-`-`- MVS Gopher Server Connection -`-`-
- +
- +Description: &GGTSUBJ
- +
- +Extracting to: &GGEXDSN
- +&MEMSTUFF
- +
- % Please wait.
- +
- )INIT
- IF (&GGEXMEM = &Z) &MEMSTUFF = &Z
- ELSE &MEMSTUFF = 'Member: &GGEXMEM'
- )PROC
- )END
- ./ ADD NAME=GGMLPRN2
- )ATTR
- /* /*
- /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1993 /*
- /* /*
- /* This software is provided on an "AS IS" basis. All warranties, /*
- /* including the implied warranties of merchantability and fitness, /*
- /* are expressly denied. /*
- /* /*
- /* Provided this copyright notice is included, this software may /*
- /* be freely distributed and not offered for sale. /*
- /* /*
- /* Changes or modifications may be made and used only by the maker /*
- /* of same, and not further distributed. Such modifications should /*
- /* be mailed to the author for consideration for addition to the /*
- /* software and incorporation in subsequent releases. /*
- /* /*
- ^ TYPE(TEXT) INTENS(HIGH) COLOR(BLUE) HILITE(REVERSE)
- @ TYPE(TEXT) INTENS(HIGH) COLOR(PINK)
- \ TYPE(TEXT) INTENS(HIGH) COLOR(YELLOW)
- ! TYPE(TEXT) INTENS(HIGH) COLOR(RED)
- $ TYPE(TEXT) INTENS(LOW) COLOR(GREEN)
- ~ TYPE(TEXT) INTENS(HIGH) COLOR(WHITE)
- )BODY EXPAND(``)
- %-`-`- MVS Gopher Server Connection -`-`-
- +
- +Description: &GGTSUBJ
- +
- +Printing to SYSOUT class: &GGEXSCL
- +&MEMSTUFF
- +
- % Please wait.
- +
- )INIT
- IF (&GGEXMEM = &Z) &MEMSTUFF = &Z
- ELSE &MEMSTUFF = 'Member: &GGEXMEM'
- )PROC
- )END
- ./ ADD NAME=GGMLSOCK
- )ATTR
- /* /*
- /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1993 /*
- /* /*
- /* This software is provided on an "AS IS" basis. All warranties, /*
- /* including the implied warranties of merchantability and fitness, /*
- /* are expressly denied. /*
- /* /*
- /* Provided this copyright notice is included, this software may /*
- /* be freely distributed and not offered for sale. /*
- /* /*
- /* Changes or modifications may be made and used only by the maker /*
- /* of same, and not further distributed. Such modifications should /*
- /* be mailed to the author for consideration for addition to the /*
- /* software and incorporation in subsequent releases. /*
- /* /*
- ^ TYPE(TEXT) INTENS(HIGH) COLOR(BLUE) HILITE(REVERSE)
- @ TYPE(TEXT) INTENS(HIGH) COLOR(PINK)
- # TYPE(TEXT) INTENS(LOW) COLOR(TURQ)
- \ TYPE(TEXT) INTENS(HIGH) COLOR(YELLOW)
- ! TYPE(TEXT) INTENS(HIGH) COLOR(RED)
- $ TYPE(TEXT) INTENS(LOW) COLOR(GREEN)
- ~ TYPE(TEXT) INTENS(HIGH) COLOR(WHITE)
- )BODY EXPAND(``)
- %-`-`- MVS Gopher Server Connection -`-`-
- +
- + Client: &CLIENT
- +
- + Connection successful.
- +
- + Retrieving data from Gopher server at:
- &SERVER
- +
- +
- % Please wait.
- +
- +
- )INIT
- &CLIENT = '&GGCLIENT (&GGCLIEIP)'
- &SERVER = '&GGSERVER (&GGSERVIP)'
- )PROC
- )END
- ./ ADD NAME=GGMOPT1
- )ATTR
- /* /*
- /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 /*
- /* /*
- /* SAS enhancements copyright (c) 1992 SAS Institute, Inc. /*
- /* /*
- /* This software is provided on an "AS IS" basis. All warranties, /*
- /* including the implied warranties of merchantability and fitness, /*
- /* are expressly denied. /*
- /* /*
- /* Provided this copyright notice is included, this software may /*
- /* be freely distributed and not offered for sale. /*
- /* /*
- /* Changes or modifications may be made and used only by the maker /*
- /* of same, and not further distributed. Such modifications should /*
- /* be mailed to the author for consideration for addition to the /*
- /* software and incorporation in subsequent releases. /*
- /* /*
- )BODY EXPAND(``)
- %-`-`- GOPHER - Directory Viewing Options -`-`-
- %Command ===>_ZCMD
- +
- +Scroll last selected menu item to top? (YES/NO)%==>_Z +
- +Put cursor at last selected menu item? (YES/NO)%==>_Z +
-
-
- +Press%ENTER+to change options. Press%&END+(or type%END+command) when done.
- )INIT
- .ZVARS = '(GGSCROLL GGCURSOR)'
- .CURSOR = ZCMD
- &END = PFK(END)
- &ZCMD = &Z
- VGET (GGSCROLL GGCURSOR) PROFILE
- &GGSCROLL = TRANS(TRUNC(&GGSCROLL,1) Y,YES N,NO *,YES)
- &GGCURSOR = TRANS(TRUNC(&GGCURSOR,1) Y,YES N,NO *,NO )
- )PROC
- IF (&ZCMD ^= &Z) .MSG = ISPZ001
- IF (.RESP = ENTER)
- &GGSCROLL = TRUNC(&GGSCROLL,1)
- &GGCURSOR = TRUNC(&GGCURSOR,1)
- VER(&GGSCROLL,NB,LIST,Y,N)
- VER(&GGCURSOR,NB,LIST,Y,N)
- VPUT (GGSCROLL GGCURSOR) PROFILE
- )END
- ./ ADD NAME=GGMOPT2
- )ATTR
- /* /*
- /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 /*
- /* /*
- /* SAS enhancements copyright (c) 1992 SAS Institute, Inc. /*
- /* /*
- /* This software is provided on an "AS IS" basis. All warranties, /*
- /* including the implied warranties of merchantability and fitness, /*
- /* are expressly denied. /*
- /* /*
- /* Provided this copyright notice is included, this software may /*
- /* be freely distributed and not offered for sale. /*
- /* /*
- /* Changes or modifications may be made and used only by the maker /*
- /* of same, and not further distributed. Such modifications should /*
- /* be mailed to the author for consideration for addition to the /*
- /* software and incorporation in subsequent releases. /*
- /* /*
- )BODY EXPAND(``)
- %-`-`- GOPHER - Miscellaneous Options -`-`-
- %Command ===>_ZCMD
- +
- %EXTRACT prompting options:
-
- +Warning panel before writing over an existing dataset?%==>_Z +
- +Warning panel before appending to an existing dataset?%==>_Z +
-
-
- +Press%ENTER+to change options. Press%&END+(or type%END+command) when done.
- )INIT
- .ZVARS = '(GGEXTPOW GGEXTPAP)'
- .CURSOR = ZCMD
- &END = PFK(END)
- &ZCMD = &Z
- VGET (GGEXTPOW GGEXTPAP) PROFILE
- &GGEXTPOW = TRANS(TRUNC(&GGEXTPOW,1) Y,YES N,NO *,YES)
- &GGEXTPAP = TRANS(TRUNC(&GGEXTPAP,1) Y,YES N,NO *,YES)
- )PROC
- IF (&ZCMD ^= &Z) .MSG = ISPZ001
- IF (.RESP = ENTER)
- &GGEXTPOW = TRUNC(&GGEXTPOW,1)
- &GGEXTPAP = TRUNC(&GGEXTPAP,1)
- VER(&GGEXTPOW,NB,LIST,Y,N)
- VER(&GGEXTPAP,NB,LIST,Y,N)
- VPUT (GGEXTPOW GGEXTPAP) PROFILE
- )END
- ./ ADD NAME=GGMPBMDS
- )ATTR
- /* /*
- /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 /*
- /* /*
- /* This software is provided on an "AS IS" basis. All warranties, /*
- /* including the implied warranties of merchantability and fitness, /*
- /* are expressly denied. /*
- /* /*
- /* Provided this copyright notice is included, this software may /*
- /* be freely distributed and not offered for sale. /*
- /* /*
- /* Changes or modifications may be made and used only by the maker /*
- /* of same, and not further distributed. Such modifications should /*
- /* be mailed to the author for consideration for addition to the /*
- /* software and incorporation in subsequent releases. /*
- /* /*
- ^ TYPE(INPUT) INTENS(HIGH) CAPS(OFF) JUST(LEFT)
- )BODY WINDOW(77,10)
- +
- %Command ===>^ZCMD
- +
- %&SUBJECT
- +
- +Bookmark data set ===>_GGBMDSN
-
- +(Note: Data set must be RECFM=VB, LRECL=259, BLKSIZE=6233.)
-
- +Press%&END (END)+to cancel the bookmark request.
- )INIT
- .CURSOR = GGBMDSN
- &ZWINTTL = 'Append bookmark'
- &SUBJECT = '&GGTSUBJ'
- &END = PFK(END)
- &ZCMD = &Z
- VGET (GGBMDSN) PROFILE
- IF (&GGBMDSN = &Z) &GGBMDSN = 'GOPHER.BOOKMARK'
- )PROC
- IF (&ZCMD ^= &Z) .MSG = ISPZ001
- VER(&GGBMDSN,NB,DSNAME)
- VPUT (GGBMDSN) PROFILE
- )END
- ./ ADD NAME=GGMPCSO
- )ATTR
- /* /*
- /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 /*
- /* /*
- /* This software is provided on an "AS IS" basis. All warranties, /*
- /* including the implied warranties of merchantability and fitness, /*
- /* are expressly denied. /*
- /* /*
- /* Provided this copyright notice is included, this software may /*
- /* be freely distributed and not offered for sale. /*
- /* /*
- /* Changes or modifications may be made and used only by the maker /*
- /* of same, and not further distributed. Such modifications should /*
- /* be mailed to the author for consideration for addition to the /*
- /* software and incorporation in subsequent releases. /*
- /* /*
- ^ TYPE(INPUT) INTENS(HIGH) CAPS(OFF) JUST(LEFT)
- )BODY WINDOW(58,10)
- +
- %Command ===>^ZCMD
- +
- +Enter name to search for:
- +
- %===>^GGCSOQ
-
- +Press%ENTER+to submit search request.
- +Press%&END (END)+to cancel the request.
- +
- )INIT
- &ZWINTTL = 'CSO Nameserver User Name Search'
- &END = PFK(END)
- .CURSOR = GGCSOQ
- )PROC
- IF (&ZCMD ^= &Z) .MSG = ISPZ001
- VER (&GGCSOQ,NB)
- VPUT (GGCSOQ) PROFILE
- )END
- ./ ADD NAME=GGMPDBM
- )ATTR
- /* /*
- /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 /*
- /* /*
- /* This software is provided on an "AS IS" basis. All warranties, /*
- /* including the implied warranties of merchantability and fitness, /*
- /* are expressly denied. /*
- /* /*
- /* Provided this copyright notice is included, this software may /*
- /* be freely distributed and not offered for sale. /*
- /* /*
- /* Changes or modifications may be made and used only by the maker /*
- /* of same, and not further distributed. Such modifications should /*
- /* be mailed to the author for consideration for addition to the /*
- /* software and incorporation in subsequent releases. /*
- /* /*
- ^ TYPE(INPUT) INTENS(HIGH) CAPS(OFF) JUST(LEFT)
- )BODY WINDOW(58,13)
- +
- %Command ===>^ZCMD
- +
- +Remove bookmark from data set &GGMDBMDS:
- +
- %&GGMDBMSU
- +
- +Press%ENTER+to update &GGMDBMDS.
- +Press%&END (END)+to cancel the request.
- +
- )INIT
- .ALARM = YES
- &ZWINTTL = 'Delete Bookmark'
- &END = PFK(END)
- )PROC
- IF (&ZCMD ^= &Z) .MSG = ISPZ001
- )END
- ./ ADD NAME=GGMPEXDS
- )ATTR
- /* /*
- /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 /*
- /* /*
- /* This software is provided on an "AS IS" basis. All warranties, /*
- /* including the implied warranties of merchantability and fitness, /*
- /* are expressly denied. /*
- /* /*
- /* Provided this copyright notice is included, this software may /*
- /* be freely distributed and not offered for sale. /*
- /* /*
- /* Changes or modifications may be made and used only by the maker /*
- /* of same, and not further distributed. Such modifications should /*
- /* be mailed to the author for consideration for addition to the /*
- /* software and incorporation in subsequent releases. /*
- /* /*
- ^ TYPE(INPUT) INTENS(HIGH) CAPS(OFF) JUST(LEFT)
- )BODY WINDOW(77,16)
- +
- %Command ===>^ZCMD
- +
- %&SUBJECT
- +
- +Save to data set ===>_GGEXDSN
- +Expand tab characters? ===>_Z +
-
- +(Note: Data set will be RECFM=VB, LRECL=259, BLKSIZE=6233.)
-
- +Append to end of data set? ===>_Z +
- +Blank line after separator? ===>_Z +
- +Separator line between items (append mode only...blank for none):
- +>^Z +<
-
- +Press%&END (END)+to cancel the extract request.
- )INIT
- .ZVARS = '(GGEXTAB GGEXAPP GGEXBLK GGEXSEP)'
- .CURSOR = GGEXDSN
- &ZWINTTL = 'Extract text'
- &SUBJECT = '&GGTSUBJ'
- &END = PFK(END)
- &ZCMD = &Z
- VGET (GGEXDSN GGEXTAB GGEXAPP GGEXBLK GGEXSEP) PROFILE
- &GGEXTAB = TRANS(&GGEXTAB Y,YES N,NO ' ',NO)
- &GGEXAPP = TRANS(&GGEXAPP Y,YES N,NO ' ',NO)
- &GGEXBLK = TRANS(&GGEXBLK Y,YES N,NO ' ',NO)
- )PROC
- IF (&ZCMD ^= &Z) .MSG = ISPZ001
- VER(&GGEXDSN,NB,DSNAME)
- &GGEXTAB = TRUNC(&GGEXTAB,1)
- VER(&GGEXTAB,NB,LIST,Y,N)
- &GGEXAPP = TRUNC(&GGEXAPP,1)
- VER(&GGEXAPP,NB,LIST,Y,N)
- &GGEXBLK = TRUNC(&GGEXBLK,1)
- VER(&GGEXBLK,NB,LIST,Y,N)
- VPUT (GGEXDSN GGEXTAB GGEXAPP GGEXBLK GGEXSEP) PROFILE
- )END
- ./ ADD NAME=GGMPEXNG
- )ATTR
- /* /*
- /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 /*
- /* /*
- /* This software is provided on an "AS IS" basis. All warranties, /*
- /* including the implied warranties of merchantability and fitness, /*
- /* are expressly denied. /*
- /* /*
- /* Provided this copyright notice is included, this software may /*
- /* be freely distributed and not offered for sale. /*
- /* /*
- /* Changes or modifications may be made and used only by the maker /*
- /* of same, and not further distributed. Such modifications should /*
- /* be mailed to the author for consideration for addition to the /*
- /* software and incorporation in subsequent releases. /*
- /* /*
- ^ TYPE(INPUT) INTENS(HIGH) CAPS(OFF) JUST(LEFT)
- )BODY WINDOW(77,14)
- +
- %Command ===>^ZCMD
- +
- +Save to data set ===>_GGEXDSN
-
- +(Note: Data set will be RECFM=VB, LRECL=259, BLKSIZE=6233.)
-
- +Append to end of data set? ===>_Z +
- +Blank line after separator? ===>_Z +
- +Separator line between items (append mode only...blank for none):
- +>^Z +<
-
- +Press%&END (END)+to cancel the extract request.
- )INIT
- .ZVARS = '(GGEXAPP GGEXBLK GGEXSEP)'
- .CURSOR = GGEXDSN
- &ZWINTTL = 'Extract item listing'
- &END = PFK(END)
- &ZCMD = &Z
- VGET (GGEXDSN GGEXAPP GGEXBLK GGEXSEP) PROFILE
- &GGEXAPP = TRANS(&GGEXAPP Y,YES N,NO ' ',NO)
- &GGEXBLK = TRANS(&GGEXBLK Y,YES N,NO ' ',NO)
- )PROC
- IF (&ZCMD ^= &Z) .MSG = ISPZ001
- VER(&GGEXDSN,NB,DSNAME)
- &GGEXAPP = TRUNC(&GGEXAPP,1)
- VER(&GGEXAPP,NB,LIST,Y,N)
- &GGEXBLK = TRUNC(&GGEXBLK,1)
- VER(&GGEXBLK,NB,LIST,Y,N)
- VPUT (GGEXDSN GGEXAPP GGEXBLK GGEXSEP) PROFILE
- )END
- ./ ADD NAME=GGMPEXNP
- )ATTR
- /* /*
- /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 /*
- /* /*
- /* This software is provided on an "AS IS" basis. All warranties, /*
- /* including the implied warranties of merchantability and fitness, /*
- /* are expressly denied. /*
- /* /*
- /* Provided this copyright notice is included, this software may /*
- /* be freely distributed and not offered for sale. /*
- /* /*
- /* Changes or modifications may be made and used only by the maker /*
- /* of same, and not further distributed. Such modifications should /*
- /* be mailed to the author for consideration for addition to the /*
- /* software and incorporation in subsequent releases. /*
- /* /*
- ^ TYPE(INPUT) INTENS(HIGH) CAPS(OFF) JUST(LEFT)
- )BODY EXPAND(``) WINDOW(77,14)
- +
- %Command ===>^ZCMD
- +
- +Data set name%===>_GGEXPDS
- +Member prefix%===>_GGEXPMP + (item number appended - default is%#+)
-
- +Note: The dataset must be a PDS (old or new) with RECFM=VB and LRECL=259.
-
- +Expand tab characters? %===>_Z +
-
- +From item number%===>_GGEXAN1 + (blank for first item in table)
- +To item number%===>_GGEXAN2 + (blank for last item in table)
-
- +Press%&END (END)+to cancel the extract request.
- )INIT
- .ZVARS = '(GGEXTAB)'
- .CURSOR = ZCMD
- &ZWINTTL = 'Log text of items to PDS members'
- &END = PFK(END)
- &ZCMD = &Z
- VGET (GGEXPDS GGEXPMP GGEXTAB) PROFILE
- &GGEXTAB = TRANS(&GGEXTAB Y,YES N,NO ' ',NO)
- IF (&GGEXPMP = &Z) &GGEXPMP = '#'
- &GGEXAN1 = &Z
- &GGEXAN2 = &Z
- )PROC
- IF (&ZCMD ^= &Z) .MSG = ISPZ001
- &GGEXTAB = TRUNC(&GGEXTAB,1)
- VER(&GGEXTAB,NB,LIST,Y,N)
- VER(&GGEXPDS,NB,DSNAME)
- &TEMP1 = TRUNC(&GGEXPDS,1)
- &TEMP2 = .TRAIL
- IF (&TEMP1 = '''')
- &GGEXDSN = TRUNC(&TEMP2,'''')
- ELSE
- &GGEXDSN = '&ZPREFIX..&GGEXPDS'
- VER(&GGEXPMP,NB,NAME)
- VER(&GGEXAN1,NUM)
- VER(&GGEXAN2,NUM)
- VPUT (GGEXPDS GGEXPMP GGEXTAB) PROFILE
- )END
- ./ ADD NAME=GGMPEXNS
- )ATTR
- /* /*
- /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 /*
- /* /*
- /* This software is provided on an "AS IS" basis. All warranties, /*
- /* including the implied warranties of merchantability and fitness, /*
- /* are expressly denied. /*
- /* /*
- /* Provided this copyright notice is included, this software may /*
- /* be freely distributed and not offered for sale. /*
- /* /*
- /* Changes or modifications may be made and used only by the maker /*
- /* of same, and not further distributed. Such modifications should /*
- /* be mailed to the author for consideration for addition to the /*
- /* software and incorporation in subsequent releases. /*
- /* /*
- ^ TYPE(INPUT) INTENS(HIGH) CAPS(OFF) JUST(LEFT)
- )BODY EXPAND(``) WINDOW(77,17)
- +
- %Command ===>^ZCMD
- +
- +Data set name%===>_GGEXSEQ
- +(Note: Data set will be RECFM=VB, LRECL=259, BLKSIZE=6233.)
- +
- +Expand tab characters? %===>_Z +
- +
- +Append to end of data set? %===>_Z +
- +Blank line after separator? %===>_Z +
- +Separator line before each item (leave blank for none):
- +>^Z +<
-
- +From item number%===>_GGEXAN1 + (blank for first item in table)
- +To item number%===>_GGEXAN2 + (blank for last item in table)
-
- +Press%&END (END)+to cancel the extract request.
- )INIT
- .ZVARS = '(GGEXTAB GGEXAPP GGEXBLK GGEXSEP)'
- .CURSOR = ZCMD
- &ZWINTTL = 'Log text of items to sequential file'
- &END = PFK(END)
- &ZCMD = &Z
- VGET (GGEXSEQ GGEXTAB GGEXAPP GGEXBLK GGEXSEP) PROFILE
- &GGEXTAB = TRANS(&GGEXTAB Y,YES N,NO ' ',NO)
- &GGEXAPP = TRANS(&GGEXAPP Y,YES N,NO ' ',NO)
- &GGEXBLK = TRANS(&GGEXBLK Y,YES N,NO ' ',NO)
- &GGEXAN1 = &Z
- &GGEXAN2 = &Z
- )PROC
- IF (&ZCMD ^= &Z) .MSG = ISPZ001
- VER(&GGEXSEQ,NB,DSNAME)
- &GGEXDSN = &GGEXSEQ
- &GGEXTAB = TRUNC(&GGEXTAB,1)
- VER(&GGEXTAB,NB,LIST,Y,N)
- &GGEXAPP = TRUNC(&GGEXAPP,1)
- VER(&GGEXAPP,NB,LIST,Y,N)
- &GGEXBLK = TRUNC(&GGEXBLK,1)
- VER(&GGEXBLK,NB,LIST,Y,N)
- VER(&GGEXAN1,NUM)
- VER(&GGEXAN2,NUM)
- VPUT (GGEXSEQ GGEXTAB GGEXAPP GGEXBLK GGEXSEP) PROFILE
- )END
- ./ ADD NAME=GGMPEXNT
- )ATTR
- /* /*
- /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 /*
- /* /*
- /* This software is provided on an "AS IS" basis. All warranties, /*
- /* including the implied warranties of merchantability and fitness, /*
- /* are expressly denied. /*
- /* /*
- /* Provided this copyright notice is included, this software may /*
- /* be freely distributed and not offered for sale. /*
- /* /*
- /* Changes or modifications may be made and used only by the maker /*
- /* of same, and not further distributed. Such modifications should /*
- /* be mailed to the author for consideration for addition to the /*
- /* software and incorporation in subsequent releases. /*
- /* /*
- ^ TYPE(INPUT) INTENS(HIGH) CAPS(OFF) JUST(LEFT)
- )BODY WINDOW(77,10)
- +
- %Command ===>^ZCMD
- +
- +Move cursor to choice (or type%S+next to choice) and press%ENTER+to select:
- +
- _A%1+- List%titles+of items in table
- _B%2+- Log %text +of items to%sequential file+
- _C%3+- Log %text +of items to%members of PDS+
- +
- +Press%&END (END)+to cancel the extract request.
- )INIT
- .CURSOR = ZCMD
- &ZWINTTL = 'Extract Gopher items - titles or text'
- &END = PFK(END)
- &ZCMD = &Z
- &A = &Z
- &B = &Z
- &C = &Z
- )PROC
- VER(&ZCMD,LIST,1,2,3)
- IF (&ZCMD ^= &Z)
- &GGCHOICE = TRANS(&ZCMD 1 1 2 2 3 3 * ?)
- ELSE
- &TEMP = '&A/&B/&C'
- IF (&TEMP = '//')
- &GGCHOICE = TRANS(.CURSOR A 1 B 2 C 3 * ?)
- ELSE
- &GGCHOICE = TRANS(&TEMP 'S//' 1
- '1//' 1
- '/S/' 2
- '/2/' 2
- '//S' 3
- '//3' 3
- * ?
- )
- )END
- ./ ADD NAME=GGMPEXN1
- )ATTR
- /* /*
- /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 /*
- /* /*
- /* This software is provided on an "AS IS" basis. All warranties, /*
- /* including the implied warranties of merchantability and fitness, /*
- /* are expressly denied. /*
- /* /*
- /* Provided this copyright notice is included, this software may /*
- /* be freely distributed and not offered for sale. /*
- /* /*
- /* Changes or modifications may be made and used only by the maker /*
- /* of same, and not further distributed. Such modifications should /*
- /* be mailed to the author for consideration for addition to the /*
- /* software and incorporation in subsequent releases. /*
- /* /*
- ^ TYPE(INPUT) INTENS(HIGH) CAPS(OFF) JUST(LEFT)
- )BODY WINDOW(77,14)
- +
- %Command ===>^ZCMD
- +
- +Save to data set ===>_GGEXDSN
-
- +(Note: Data set will be RECFM=VB, LRECL=259, BLKSIZE=6233.)
-
- +Append to end of data set? ===>_Z +
- +Blank line after separator? ===>_Z +
- +Separator line between items (append mode only...blank for none):
- +>^Z +<
-
- +Press%&END (END)+to cancel the extract request.
- )INIT
- .ZVARS = '(GGEXAPP GGEXBLK GGEXSEP)'
- .CURSOR = GGEXDSN
- &ZWINTTL = 'Extract Gopher item listing'
- &END = PFK(END)
- &ZCMD = &Z
- VGET (GGEXDSN GGEXAPP GGEXBLK GGEXSEP) PROFILE
- &GGEXAPP = TRANS(&GGEXAPP Y,YES N,NO ' ',NO)
- &GGEXBLK = TRANS(&GGEXBLK Y,YES N,NO ' ',NO)
- )PROC
- IF (&ZCMD ^= &Z) .MSG = ISPZ001
- VER(&GGEXDSN,NB,DSNAME)
- &GGEXAPP = TRUNC(&GGEXAPP,1)
- VER(&GGEXAPP,NB,LIST,Y,N)
- &GGEXBLK = TRUNC(&GGEXBLK,1)
- VER(&GGEXBLK,NB,LIST,Y,N)
- VPUT (GGEXDSN GGEXAPP GGEXBLK GGEXSEP) PROFILE
- )END
- ./ ADD NAME=GGMPEXOW
- )ATTR
- /* /*
- /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 /*
- /* /*
- /* This software is provided on an "AS IS" basis. All warranties, /*
- /* including the implied warranties of merchantability and fitness, /*
- /* are expressly denied. /*
- /* /*
- /* Provided this copyright notice is included, this software may /*
- /* be freely distributed and not offered for sale. /*
- /* /*
- /* Changes or modifications may be made and used only by the maker /*
- /* of same, and not further distributed. Such modifications should /*
- /* be mailed to the author for consideration for addition to the /*
- /* software and incorporation in subsequent releases. /*
- /* /*
- ^ TYPE(INPUT) INTENS(HIGH) CAPS(OFF) JUST(LEFT)
- )BODY WINDOW(58,10)
- +
- %Command ===>^ZCMD
- +
- +Dataset already exists:
- +
- %&GGEXDSN
- +
- +Press%ENTER+to%&ACTION
- +Press%&END (END)+to cancel the request.
- +
- )INIT
- .ALARM = YES
- &ZWINTTL = 'Extract To Existing Data Set'
- &END = PFK(END)
- &APP = TRUNC(&GGEXAPP,1)
- IF (&APP = Y) &ACTION = 'append to the end of the data set.'
- ELSE &ACTION = 'overwrite the current data set.'
- )PROC
- IF (&ZCMD ^= &Z) .MSG = ISPZ001
- )END
- ./ ADD NAME=GGMPEXPW
- )ATTR
- /* /*
- /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 /*
- /* /*
- /* This software is provided on an "AS IS" basis. All warranties, /*
- /* including the implied warranties of merchantability and fitness, /*
- /* are expressly denied. /*
- /* /*
- /* Provided this copyright notice is included, this software may /*
- /* be freely distributed and not offered for sale. /*
- /* /*
- /* Changes or modifications may be made and used only by the maker /*
- /* of same, and not further distributed. Such modifications should /*
- /* be mailed to the author for consideration for addition to the /*
- /* software and incorporation in subsequent releases. /*
- /* /*
- ^ TYPE(INPUT) INTENS(HIGH) CAPS(OFF) JUST(LEFT)
- )BODY WINDOW(58,13)
- +
- %Command ===>^ZCMD
- +
- +Partitioned dataset already exists:
- +
- %&GGEXDSN
- +
- +If member names are generated that match existing members
- +of this PDS, they will be%overwritten.+
- +
- +Press%ENTER+to proceed to use this PDS.
- +Press%&END (END)+to cancel the request.
- +
- )INIT
- .ALARM = YES
- &ZWINTTL = 'Extract To Members of Existing PDS'
- &END = PFK(END)
- )PROC
- IF (&ZCMD ^= &Z) .MSG = ISPZ001
- )END
- ./ ADD NAME=GGMPOPT
- )ATTR
- /* /*
- /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 /*
- /* /*
- /* This software is provided on an "AS IS" basis. All warranties, /*
- /* including the implied warranties of merchantability and fitness, /*
- /* are expressly denied. /*
- /* /*
- /* Provided this copyright notice is included, this software may /*
- /* be freely distributed and not offered for sale. /*
- /* /*
- /* Changes or modifications may be made and used only by the maker /*
- /* of same, and not further distributed. Such modifications should /*
- /* be mailed to the author for consideration for addition to the /*
- /* software and incorporation in subsequent releases. /*
- /* /*
- ^ TYPE(INPUT) INTENS(HIGH) CAPS(OFF) JUST(LEFT)
- )BODY WINDOW(77,10)
- +
- %Command ===>^ZCMD
- +
- +Move cursor to choice (or type%S+next to choice) and press%ENTER+to select:
- +
- _Z%1+- Display viewing options
- _Z%2+- Other options
- +
- +Press%&END (END)+to return to the previous panel.
- )INIT
- .ZVARS = '(S1 S2)'
- .CURSOR = ZCMD
- &ZWINTTL = 'Customize user options'
- &END = PFK(END)
- &ZCMD = &Z
- &S1 = &Z
- &S2 = &Z
- )PROC
- IF (&ZCMD ^= &Z)
- &GGCHOICE = TRANS(&ZCMD 1 1 2 2 * ?)
- ELSE
- &TEMP = '&S1/&S2'
- IF (&TEMP = '/')
- &GGCHOICE = TRANS(.CURSOR S1 1 S2 2 * ?)
- ELSE
- &GGCHOICE = TRANS(&TEMP 'S/' 1
- '1/' 1
- '/S' 2
- '/2' 2
- * ?
- )
- )END
- ./ ADD NAME=GGMPPRDS
- )ATTR
- /* /*
- /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1993 /*
- /* /*
- /* This software is provided on an "AS IS" basis. All warranties, /*
- /* including the implied warranties of merchantability and fitness, /*
- /* are expressly denied. /*
- /* /*
- /* Provided this copyright notice is included, this software may /*
- /* be freely distributed and not offered for sale. /*
- /* /*
- /* Changes or modifications may be made and used only by the maker /*
- /* of same, and not further distributed. Such modifications should /*
- /* be mailed to the author for consideration for addition to the /*
- /* software and incorporation in subsequent releases. /*
- /* /*
- ^ TYPE(INPUT) INTENS(HIGH) CAPS(OFF) JUST(LEFT)
- # TYPE(TEXT) INTENS(LOW)
- @ TYPE(INPUT) INTENS(HIGH) CAPS(ON) JUST(LEFT)
- )BODY WINDOW(77,12)
- +
- %Command ===>^ZCMD
- +
- %&SUBJECT
- +
- +SYSOUT class ===>_Z+ Number of copies ===>_Z +
- #Destination ===>@DESTUSR # Forms ===>@Z # UCS ===>@Z +
-
- +(Note: Print data will be released to SYSOUT immediately.)
-
-
- +Press%&END (END)+to cancel the print request.
- )INIT
- .ZVARS = '(GGEXSCL GGEXSCO GGEXSFO GGEXSUC)'
- .CURSOR = GGEXSCL
- &ZWINTTL = 'Print text'
- &SUBJECT = '&GGTSUBJ'
- &END = PFK(END)
- &ZCMD = &Z
- &GGEXSCO = 1
- &PVARS = 'GGEXSCL'
- IF (&GGALLPR ^= &Z)
- &PVARS = '&PVARS GGEXSDE GGEXSUS GGEXSFO GGEXSUC'
- .ATTRCHAR('#') = 'TYPE(TEXT) INTENS(LOW)'
- .ATTRCHAR('@') = 'TYPE(INPUT) INTENS(HIGH) CAPS(ON) JUST(LEFT)'
- ELSE
- .ATTRCHAR('#') = 'TYPE(TEXT) INTENS(NON)'
- .ATTRCHAR('@') = 'TYPE(OUTPUT) INTENS(NON)'
- VGET (&PVARS) PROFILE
- &DESTUSR = &GGEXSDE
- IF (&GGEXSDE ^= &Z)
- IF (&GGEXSUS ^= &Z)
- &DESTUSR = '&GGEXSDE..&GGEXSUS'
- )PROC
- IF (&ZCMD ^= &Z) .MSG = ISPZ001
- VER(&GGEXSCL,NB)
- IF (&GGEXSCO = &Z) &GGEXSCO = 1
- VER(&GGEXSCO,NUM)
- VER(&GGEXSCO,RANGE,1,255)
- &GGEXSDE = TRUNC(&DESTUSR,'.')
- &GGEXSUS = .TRAIL
- VPUT (&PVARS) PROFILE
- )END
- ./ ADD NAME=GGMPWAIS
- )ATTR
- /* /*
- /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 /*
- /* /*
- /* This software is provided on an "AS IS" basis. All warranties, /*
- /* including the implied warranties of merchantability and fitness, /*
- /* are expressly denied. /*
- /* /*
- /* Provided this copyright notice is included, this software may /*
- /* be freely distributed and not offered for sale. /*
- /* /*
- /* Changes or modifications may be made and used only by the maker /*
- /* of same, and not further distributed. Such modifications should /*
- /* be mailed to the author for consideration for addition to the /*
- /* software and incorporation in subsequent releases. /*
- /* /*
- ^ TYPE(INPUT) INTENS(HIGH) CAPS(OFF) JUST(LEFT)
- )BODY WINDOW(58,10)
- +
- %Command ===>^ZCMD
- +
- +Enter index search query:
- +
- %===>^GGWAISQ
-
- +Press%ENTER+to submit search request.
- +Press%&END (END)+to cancel the request.
- +
- )INIT
- &ZWINTTL = 'GOPHER Full Text Index Search'
- &END = PFK(END)
- .CURSOR = GGWAISQ
- )PROC
- IF (&ZCMD ^= &Z) .MSG = ISPZ001
- VER (&GGWAISQ,NB)
- VPUT (GGWAISQ) PROFILE
- )END
- ./ ADD NAME=GGMPWHOI
- )ATTR
- /* /*
- /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 /*
- /* /*
- /* This software is provided on an "AS IS" basis. All warranties, /*
- /* including the implied warranties of merchantability and fitness, /*
- /* are expressly denied. /*
- /* /*
- /* Provided this copyright notice is included, this software may /*
- /* be freely distributed and not offered for sale. /*
- /* /*
- /* Changes or modifications may be made and used only by the maker /*
- /* of same, and not further distributed. Such modifications should /*
- /* be mailed to the author for consideration for addition to the /*
- /* software and incorporation in subsequent releases. /*
- /* /*
- ^ TYPE(INPUT) INTENS(HIGH) CAPS(OFF) JUST(LEFT)
- )BODY WINDOW(58,10)
- +
- %Command ===>^ZCMD
- +
- +Enter name to search for:
- +
- %===>^GGWHOISQ
-
- +Press%ENTER+to submit search request.
- +Press%&END (END)+to cancel the request.
- +
- )INIT
- &ZWINTTL = 'WHOIS/FINGER User Name Search'
- &END = PFK(END)
- .CURSOR = GGWHOISQ
- )PROC
- IF (&ZCMD ^= &Z) .MSG = ISPZ001
- VER (&GGWHOISQ,NB)
- VPUT (GGWHOISQ) PROFILE
- )END
- ./ ADD NAME=GGMVIEW
- )ATTR DEFAULT(%+_)
- /* */
- /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1993 */
- /* */
- /* This software is provided on an "AS IS" basis. All warranties, */
- /* including the implied warranties of merchantability and fitness, */
- /* are expressly denied. */
- /* */
- /* Provided this copyright notice is included, this software may */
- /* be freely distributed and not offered for sale. */
- /* */
- /* Changes or modifications may be made and used only by the maker */
- /* of same, and not further distributed. Such modifications should */
- /* be mailed to the author for consideration for addition to the */
- /* software and incorporation in subsequent releases. */
- /* */
- ^ TYPE(INPUT) INTENS(HIGH) CAPS(OFF) JUST(LEFT)
- # TYPE(OUTPUT) INTENS(HIGH) CAPS(OFF) JUST(RIGHT)
- \ TYPE(OUTPUT) INTENS(HIGH) CAPS(OFF) JUST(LEFT)
- | AREA(DYNAMIC) EXTEND(ON) SCROLL(ON) USERMOD(05)
- 01 TYPE(DATAOUT) INTENS(LOW)
- 02 TYPE(DATAOUT) INTENS(HIGH)
- 03 TYPE(DATAIN) INTENS(LOW)
- 04 TYPE(DATAIN) INTENS(HIGH)
- )BODY
- \GGBTITLE
- %COMMAND ===>^ZCMD %SCROLL ===>_Z +
- |GGBDYNA |
- )INIT
- .ZVARS = GGMBROSC
- IF (&GGMBROSC = &Z) &GGMBROSC = CSR
- .CURSOR = &GGBCUR
- .CSRPOS = &GGBPOS
- )PROC
- &GGBCUR = .CURSOR
- &GGBPOS = .CSRPOS
- &GGBLVL = LVLINE(GGBDYNA)
- VPUT (GGMBROSC) PROFILE
- )END
- ./ ENDUP
- ?!
-